knitr::opts_chunk$set(echo = TRUE)
rm(list = ls())
#install.packages("ona", repos = c("https://cran.qe-libs.org", "https://cran.rstudio.org")) # only run once
#install.packages("tma", repos = c("https://cran.qe-libs.org", "https://cran.rstudio.org")) # only run once

most recent data Ayano shared

data <- read.csv("~/Rprojects/ayano/PES_010v6(selected).csv")
units <- c("Speaker", "Role", "TimePhase")

codes_1 <- c("Functions", "Aesthetics", "User", "Vision", "Prototyping") # design actions codes
codes_2 <- c("CA", "ALoK", "CSU", "GCA", "Projective","Regulative","Relational") # shared epistemic agency codes

hoo_rules <- conversation_rules(
  (TimePhase %in% UNIT$TimePhase & Role %in% UNIT$Role)
)

notes: accum_1 and set_1 are for design action codes; accum_2 and set_2 are for shared epistemic agency codes

accum_1 <-
  contexts(data, 
           units_by = units, 
           hoo_rules = hoo_rules) %>%
  accumulate_contexts(codes = codes_1, 
                      decay.function = decay(simple_window, window_size = 4),
                      return.ena.set = FALSE, norm.by = NULL)

Note: Not doing means rotation so I can compare everything in the same space

set_1 <-
  # model(accum_1,
  #       rotate.using = "mean",
  #       rotation.params = 
  #         list(engineers=accum_1$meta.data$Role=="Engineer",
  #              servicedesigners=accum_1$meta.data$Role=="ServiceDesigner"))
  
  model(accum_1)
set_1 <-
  # model(accum_1,
  #       rotate.using = "mean",
  #       rotation.params = 
  #         list(engineers=accum_1$meta.data$Role=="Engineer",
  #              servicedesigners=accum_1$meta.data$Role=="ServiceDesigner"))
  
  model(accum_1)
set_2 <-
  # model(accum_2,
  #       rotate.using = "mean",
  #       rotation.params = 
  #         list(engineers=accum_2$meta.data$Role=="Engineer",
  #              servicedesigners=accum_2$meta.data$Role=="ServiceDesigner"))
  
  model(accum_2)

global visual parameter (let’s make sure all the plots use the same level of multiplier)

set_2 <-
  # model(accum_2,
  #       rotate.using = "mean",
  #       rotation.params = 
  #         list(engineers=accum_2$meta.data$Role=="Engineer",
  #              servicedesigners=accum_2$meta.data$Role=="ServiceDesigner"))
  
  model(accum_2)

Model 1: design action codes

Plot 1a: Overall Group Comparisons

traces = c(2:10)
plot(set_1, title = "Groups") |>
  units(
    points= set_1$points$Role$ProductDesigner, 
    point_position_multiplier = point_position_multiplier,
    points_color = c("red"),
    show_mean = TRUE, show_points = FALSE, with_ci = TRUE) |>
   units(
    points= set_1$points$Role$Engineer, 
    point_position_multiplier = point_position_multiplier,
    points_color = c("blue"),
    show_mean = TRUE, show_points = FALSE, with_ci = TRUE) |>
   units(
    points= set_1$points$Role$ServiceDesigner, 
    point_position_multiplier = point_position_multiplier,
    points_color = c("green"),
    show_mean = TRUE, show_points = FALSE, with_ci = TRUE) |>
  nodes(node_size_multiplier = 0.3,
            node_position_multiplier = node_position_multiplier,
            self_connection_color = c("black"))|>
      plotly::layout(showlegend = TRUE, legend = list(x = 100, y = 0.9)) |>
      plotly::style(name = "Product Designer", traces = traces[1]) |>
      plotly::style(name = "Engineer", traces = traces[2]) |>
      plotly::style(name = "Service Designer", traces = traces[3])
NA

Plot 1b: Group subtractions

prod_pts = set_1$points$Role$ProductDesigner 
eng_pts = set_1$points$Role$Engineer
serv_pts = set_1$points$Role$ServiceDesigner

prod_mean_net = set_1$line.weights %>% dplyr::filter(Role == "ProductDesigner") %>% colMeans()
eng_mean_net = set_1$line.weights %>% dplyr::filter(Role == "Engineer") %>% colMeans()
serv_mean_net = set_1$line.weights %>% dplyr::filter(Role == "ServiceDesigner") %>% colMeans()

plot(set_1, title = "Product Designer vs Engineer") |>
  units(
    points = prod_pts, 
    points_color = "red",
    show_mean = TRUE, show_points = FALSE, with_ci = TRUE) |>
  units(
    points = eng_pts, 
    points_color = "blue",
    show_mean = TRUE, show_points = FALSE, with_ci = TRUE) |>
  edges(
    weights = prod_mean_net - eng_mean_net, # optional multiplier to adjust for readability
    edge_size_multiplier = edge_size_multiplier,
    edge_arrow_saturation_multiplier = edge_arrow_saturation_multiplier,
    node_position_multiplier = node_position_multiplier,
    edge_color = c("red","blue")) |>
  nodes(
    node_size_multiplier = node_size_multiplier,
    node_position_multiplier = node_position_multiplier,
    self_connection_color = c("red","blue"))

plot(set_1, title = "Product Designer vs ServiceDesigner") |>
  units(
    points = prod_pts, 
    points_color = "red",
    show_mean = TRUE, show_points = FALSE, with_ci = TRUE) |>
  units(
    points =serv_pts, 
    points_color = "green",
    show_mean = TRUE, show_points = FALSE, with_ci = TRUE) |>
  edges(
    weights = prod_mean_net - serv_mean_net, # optional multiplier to adjust for readability
    edge_size_multiplier = edge_size_multiplier,
    edge_arrow_saturation_multiplier = edge_arrow_saturation_multiplier,
    node_position_multiplier = node_position_multiplier,
    edge_color = c("red","green")) |>
  nodes(
    node_size_multiplier = node_size_multiplier,
    node_position_multiplier = node_position_multiplier,
    self_connection_color = c("red","green"))

plot(set_1, title = "Service Designer vs Engineer") |>
  units(
    points = serv_pts, 
    points_color = "green",
    show_mean = TRUE, show_points = FALSE, with_ci = TRUE) |>
  units(
    points = eng_pts, 
    points_color = "blue",
    show_mean = TRUE, show_points = FALSE, with_ci = TRUE) |>
  edges(
    weights = serv_mean_net - eng_mean_net, # optional multiplier to adjust for readability
    edge_size_multiplier = edge_size_multiplier,
    edge_arrow_saturation_multiplier = edge_arrow_saturation_multiplier,
    node_position_multiplier = node_position_multiplier,
    edge_color = c("green","blue")) |>
  nodes(
    node_size_multiplier = node_size_multiplier,
    node_position_multiplier = node_position_multiplier,
    self_connection_color = c("green","blue"))

Plot 2: All Means by phase


#get list of time phases and groups loop over or use map function

phases = unique(set_1$points$TimePhase)

groups = unique(set_1$points$Role)

col_list_2 = c("red",#phase 1
              "blue", #phase 2
              "green") #phase 3

traces = c(2:10)

x = plot(set_1, title = "Group Means by Phase")
count = 1
for (i in 1:length(phases)){
  for (j in 1:length(groups)){
    points = set_1$points %>% filter(TimePhase == phases[i], Role == groups[j])
    x = x |>
      units(
        points = points,
        point_position_multiplier = point_position_multiplier,
        points_color = col_list_2[i],
        show_mean = TRUE, show_points = F, with_ci = FALSE
        ) |>
      nodes(node_size_multiplier = 0.3,
            node_position_multiplier = node_position_multiplier,
            self_connection_color = c("black"))|>
      plotly::layout(showlegend = TRUE, legend = list(x = 100, y = 0.9)) |>
      plotly::style(name = paste0(phases[i]," - ",groups[j]), traces = traces[count])
    count = count + 1
  }
}

x
NA

Statistical Tests:

In these data, the observations are nested within participants, so we need to check if this nesting has a significant effect. We do this by constructing a confidence interval around the intraclass correlation coefficient (https://en.wikipedia.org/wiki/Intraclass_correlation). If the interval contains zero, nesting is not significant.

reg_dat = set_1$points %>% filter(ENA_DIRECTION == "response")

ICC::ICCest(Speaker,SVD1,reg_dat) #not significant
Warning: 'x' has been coerced to a factor
$ICC
[1] 0.05242903

$LowerCI
[1] -0.2098135

$UpperCI
[1] 0.5007296

$N
[1] 10

$k
[1] 3.272727

$varw
[1] 0.3002277

$vara
[1] 0.01661158
ICC::ICCest(Speaker,SVD2,reg_dat) #not significant
Warning: 'x' has been coerced to a factor
$ICC
[1] -0.1818112

$LowerCI
[1] -0.3333495

$UpperCI
[1] 0.1964787

$N
[1] 10

$k
[1] 3.272727

$varw
[1] 0.07137526

$vara
[1] -0.01098045

Nesting is not significant so we proceed with an OLS regression. Below we set up two models for each dimension and test whether including interaction effects in the analysis significantly improves the modes.

mod_x = lm(SVD1 ~ as.factor(TimePhase) + Role, data = reg_dat)
mod_y = lm(SVD2 ~ as.factor(TimePhase) + Role, data = reg_dat)

mod_x_2 = lm(SVD1 ~ as.factor(TimePhase)*Role, data = reg_dat)
anova(mod_x,mod_x_2)
Analysis of Variance Table

Model 1: SVD1 ~ as.factor(TimePhase) + Role
Model 2: SVD1 ~ as.factor(TimePhase) * Role
  Res.Df    RSS Df Sum of Sq      F  Pr(>F)  
1     28 2.6341                              
2     24 1.7559  4   0.87815 3.0006 0.03851 *
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
mod_y_2 = lm(SVD2 ~ as.factor(TimePhase)*Role, data = reg_dat)
anova(mod_y,mod_y_2)
Analysis of Variance Table

Model 1: SVD2 ~ as.factor(TimePhase) + Role
Model 2: SVD2 ~ as.factor(TimePhase) * Role
  Res.Df    RSS Df Sum of Sq      F   Pr(>F)    
1     28 1.1117                                 
2     24 0.2156  4   0.89614 24.939 3.02e-08 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Interactions are significant, so we should use the interaction models. Let’s view those models

summary(mod_x_2)

Call:
lm(formula = SVD1 ~ as.factor(TimePhase) * Role, data = reg_dat)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.85356 -0.01457  0.00790  0.08624  0.32816 

Coefficients:
                                          Estimate Std. Error t value Pr(>|t|)   
(Intercept)                                -0.1652     0.1352  -1.221  0.23385   
as.factor(TimePhase)2                       0.7013     0.2066   3.395  0.00239 **
as.factor(TimePhase)3                       0.6249     0.2066   3.025  0.00585 **
RoleProductDesigner                        -0.5044     0.1913  -2.637  0.01443 * 
RoleServiceDesigner                        -0.6041     0.1913  -3.158  0.00425 **
as.factor(TimePhase)2:RoleProductDesigner   0.1937     0.2815   0.688  0.49803   
as.factor(TimePhase)3:RoleProductDesigner   0.6236     0.2922   2.134  0.04324 * 
as.factor(TimePhase)2:RoleServiceDesigner  -0.2347     0.2815  -0.834  0.41272   
as.factor(TimePhase)3:RoleServiceDesigner   0.6444     0.2815   2.289  0.03117 * 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.2705 on 24 degrees of freedom
Multiple R-squared:  0.8261,    Adjusted R-squared:  0.7681 
F-statistic: 14.25 on 8 and 24 DF,  p-value: 2.062e-07
summary(mod_y_2)

Call:
lm(formula = SVD2 ~ as.factor(TimePhase) * Role, data = reg_dat)

Residuals:
      Min        1Q    Median        3Q       Max 
-0.196826 -0.035322 -0.001122  0.020930  0.273378 

Coefficients:
                                          Estimate Std. Error t value Pr(>|t|)    
(Intercept)                               -0.17794    0.04739  -3.755 0.000977 ***
as.factor(TimePhase)2                     -0.08890    0.07239  -1.228 0.231326    
as.factor(TimePhase)3                      0.62627    0.07239   8.651 7.68e-09 ***
RoleProductDesigner                        0.24264    0.06702   3.620 0.001366 ** 
RoleServiceDesigner                        0.29823    0.06702   4.450 0.000168 ***
as.factor(TimePhase)2:RoleProductDesigner  0.06701    0.09865   0.679 0.503477    
as.factor(TimePhase)3:RoleProductDesigner -0.35748    0.10237  -3.492 0.001880 ** 
as.factor(TimePhase)2:RoleServiceDesigner -0.27608    0.09865  -2.799 0.009962 ** 
as.factor(TimePhase)3:RoleServiceDesigner -0.93799    0.09865  -9.508 1.30e-09 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.09478 on 24 degrees of freedom
Multiple R-squared:   0.89, Adjusted R-squared:  0.8534 
F-statistic: 24.28 on 8 and 24 DF,  p-value: 1.032e-09

Viewing interactions

emmip(mod_x_2, Role ~ TimePhase)

emmip(mod_y_2, Role ~ TimePhase)

When interactions are introduced, interpreting regression coefficients becomes more difficult, so we calculated the marginal means and various contrasts (i.e., comparisons between groups of interest) to address our research questions.

RQ1 (X dimension - Design Actions): Here we want to compare the “main effect” of Role on the x dimension—i.e., are there differences between the roles on the X dimension when averaging over TimePhases.

emm_x1 = emmeans(mod_x_2, specs = pairwise ~ Role, weights = "proportional")
NOTE: Results may be misleading due to involvement in interactions
print(emm_x1$contrasts)
 contrast                          estimate    SE df t.ratio p.value
 Engineer - ProductDesigner           0.251 0.119 24   2.116  0.1077
 Engineer - ServiceDesigner           0.487 0.116 24   4.192  0.0009
 ProductDesigner - ServiceDesigner    0.236 0.113 24   2.085  0.1142

Results are averaged over the levels of: TimePhase 
P value adjustment: tukey method for comparing a family of 3 estimates 

Only significant difference on the X is between Engineer and Service designer. Let’s calculate the effect size (difference in standard deviations) of that difference. We will use Cohen’s d.

cohensd = function(diff_,g1,g2){
  diff_/(sqrt((sd(g1)^2 + sd(g2)^2)/2))
}

contrasts = as_tibble(emm_x1$contrasts)
diff_ = contrasts$estimate[2]
g1 = reg_dat %>% filter(Role == "Engineer") %>% select(SVD1)
g2 = reg_dat %>% filter(Role == "ServiceDesigner") %>% select(SVD1)

cohensd(diff_ = diff_,g1 = g1$SVD1,g2 = g2$SVD1)
[1] 0.9779281

RQ1 (Y dimension - Design Actions): Here we want to compare the “main effect” of Role on the y dimension—i.e., are there differences between the roles on the X dimension when averaging over TimePhases.

emm_y1 = emmeans(mod_y_2, specs = pairwise ~ Role, weights = "proportional")
NOTE: Results may be misleading due to involvement in interactions
print(emm_y1$contrasts)
 contrast                          estimate     SE df t.ratio p.value
 Engineer - ProductDesigner          -0.157 0.0415 24  -3.771  0.0026
 Engineer - ServiceDesigner           0.078 0.0407 24   1.917  0.1556
 ProductDesigner - ServiceDesigner    0.235 0.0397 24   5.915  <.0001

Results are averaged over the levels of: TimePhase 
P value adjustment: tukey method for comparing a family of 3 estimates 

Significant differences between engineer/product designer and productdesigner/servicedesigner. Let’s get the effect sizes:

contrasts = as_tibble(emm_y1$contrasts)

diff_evp = contrasts$estimate[1]
g1 = reg_dat %>% filter(Role == "Engineer") %>% select(SVD1)
g2 = reg_dat %>% filter(Role == "ProductDesigner") %>% select(SVD1)

d_evp = cohensd(diff_ = diff_,g1 = g1$SVD1,g2 = g2$SVD1)

diff_pvs = contrasts$estimate[3]
g1 = reg_dat %>% filter(Role == "ProductDesigner") %>% select(SVD1)
g2 = reg_dat %>% filter(Role == "ServiceDesigner") %>% select(SVD1)

d_pvs = cohensd(diff_ = diff_,g1 = g1$SVD1,g2 = g2$SVD1)

d_evp
[1] 0.9137988
d_pvs
[1] 0.8072687

Marginal means - x RQ2

Here we use marginal means to test for differences between timephases within groups and groups within timephase and

library(emmeans)

emm_x1a = emmeans(mod_x_2, specs = pairwise ~ TimePhase|Role, weights = "proportional") #timephases w/n groups
emm_x1a = as_tibble(emm_x1a$contrasts)

emm_x2 = emmeans(mod_x_2, specs = pairwise ~ Role|TimePhase, weights = "proportional") #groups w/n timephases
emm_x2 = as_tibble(emm_x2$contrasts)

#see here: https://cran.r-project.org/web/packages/emmeans/vignettes/interactions.html

emm_x1a = emm_x1a %>% filter(p.value < 0.05)
emm_x2 = emm_x2 %>% filter(p.value < 0.05)

emm_x1a
emm_x2
NA

Several contrasts are significant. Let’s calculate the effect sizes

print(list(t1_evp,t1_evs,t2_evs,t2_pvs))
[[1]]
[1] 1.826995

[[2]]
[1] 2.233997

[[3]]
[1] 4.14715

[[4]]
[1] 1.169235

Some of these are too large to be trusted. This is happening because some individuals are highly similar in the data. We will have to acknowledge this as it is likely due to small sample size

Marginal means -Y RQ2: Let’s repeate what we did for X here

emm_y1 = emmeans(mod_y_2, specs = pairwise ~ TimePhase|Role, weights = "proportional")
emm_y1 = as_tibble(emm_y1$contrasts)

emm_y2 = emmeans(mod_y_2, specs = pairwise ~ Role|TimePhase, weights = "proportional")
emm_y2 = as_tibble(emm_y2$contrasts)

emm_y1 = emm_y1 %>% filter(p.value < 0.05)
emm_y2 = emm_y2 %>% filter(p.value < 0.05)

emm_y1
emm_y2

Several contrasts are significant. Let’s calculate the effect sizes

print(list(t1_ep_y,t1_es_y,t2_ep_y,t2_ps_y,t3_es_y,t3_ps_y))
[[1]]
[1] -2.082427

[[2]]
[1] -2.734181

[[3]]
[1] -13.53816

[[4]]
[1] 2.197361

[[5]]
[1] 8.972244

[[6]]
[1] 8.239644

Model diagnostics

library(performance)
library(see)

check_model(mod_x_2)
Model has interaction terms. VIFs might be inflated.
  You may check multicollinearity among predictors of a model without interaction terms.

check_model(mod_y_2)
Model has interaction terms. VIFs might be inflated.
  You may check multicollinearity among predictors of a model without interaction terms.

Things look ok for the most part

Plot network subtractions (replace TimePhase and Role for different combinations)

mean1 = set_1$points %>% dplyr::filter(TimePhase == 1, Role == "Engineer") #update here
mean2 = set_1$points %>% dplyr::filter(TimePhase == 1, Role == "ServiceDesigner") #update here

mean1_net = set_1$line.weights %>% dplyr::filter(TimePhase == 1, Role == "Engineer") %>% colMeans()
mean2_net = set_1$line.weights %>% dplyr::filter(TimePhase == 1, Role == "ServiceDesigner") %>% colMeans() #update here

plot(set_1, title = "Network subtraction") |>
  units(
    points = mean1, 
    points_color = "red",
    show_mean = TRUE, show_points = FALSE, with_ci = TRUE) |>
  units(
    points = mean2, 
    points_color = "blue",
    show_mean = TRUE, show_points = FALSE, with_ci = TRUE) |>
  edges(
    weights = mean1_net - mean2_net, # optional multiplier to adjust for readability
    edge_size_multiplier = edge_size_multiplier,
    edge_arrow_saturation_multiplier = edge_arrow_saturation_multiplier,
    node_position_multiplier = node_position_multiplier,
    edge_color = c("red","blue")) |>
  nodes(
    node_size_multiplier = node_size_multiplier,
    node_position_multiplier = node_position_multiplier,
    self_connection_color = c("red","blue"))

Model 2: Epistemic Agency Codes

Plot 1: Mean Network

node_size_multiplier = 0.3 # scale up or down node sizes
node_position_multiplier = 1 # zoom in or out node positions
point_position_multiplier = 1 # zoom in or out the point positions
edge_arrow_saturation_multiplier = 1.5 # adjust the chevron color lighter or darker
edge_size_multiplier = 2 # scale up or down edge sizes
plot(set_2, title = "Overall Mean--Agency") |>
  units(
    points= set_2$points, 
    point_position_multiplier = point_position_multiplier,
    points_color = c("black"),
    show_mean = TRUE, show_points = TRUE, with_ci = TRUE) |>
  edges(
    weights =set_2$line.weights,
    edge_size_multiplier = edge_size_multiplier,
    edge_arrow_saturation_multiplier = edge_arrow_saturation_multiplier,
    node_position_multiplier = node_position_multiplier,
    edge_color = c("black")) |>
  nodes(
    node_size_multiplier = node_size_multiplier,
    node_position_multiplier = node_position_multiplier,
    node_labels = TRUE, # change this to FALSE can remove node labels in case you want to add them back in a nicer font or size for your presentations or publications
    self_connection_color = c("black"))

Plot 1b: Overall Group Comparisons

plot(set_2, title = "Groups") |>
  units(
    points= set_2$points$Role$ProductDesigner, 
    point_position_multiplier = point_position_multiplier,
    points_color = c("red"),
    show_mean = TRUE, show_points = FALSE, with_ci = TRUE) |>
   units(
    points= set_2$points$Role$Engineer, 
    point_position_multiplier = point_position_multiplier,
    points_color = c("blue"),
    show_mean = TRUE, show_points = FALSE, with_ci = TRUE) |>
   units(
    points= set_2$points$Role$ServiceDesigner, 
    point_position_multiplier = point_position_multiplier,
    points_color = c("green"),
    show_mean = TRUE, show_points = FALSE, with_ci = TRUE) |>
  nodes(node_size_multiplier = 0.3,
            node_position_multiplier = node_position_multiplier,
            self_connection_color = c("black"))|>
      plotly::layout(showlegend = TRUE, legend = list(x = 100, y = 0.9)) |>
      plotly::style(name = "Product Designer", traces = traces[1]) |>
      plotly::style(name = "Engineer", traces = traces[2]) |>
      plotly::style(name = "Service Designer", traces = traces[3])
  

Plot 1c: Group subtractions

prod_pts = set_2$points$Role$ProductDesigner 
eng_pts = set_2$points$Role$Engineer
serv_pts = set_2$points$Role$ServiceDesigner

prod_mean_net = set_2$line.weights %>% dplyr::filter(Role == "ProductDesigner") %>% colMeans()
eng_mean_net = set_2$line.weights %>% dplyr::filter(Role == "Engineer") %>% colMeans()
serv_mean_net = set_2$line.weights %>% dplyr::filter(Role == "ServiceDesigner") %>% colMeans()

plot(set_2, title = "Product Designer vs Engineer") |>
  units(
    points = prod_pts, 
    points_color = "red",
    show_mean = TRUE, show_points = FALSE, with_ci = TRUE) |>
  units(
    points = eng_pts, 
    points_color = "blue",
    show_mean = TRUE, show_points = FALSE, with_ci = TRUE) |>
  edges(
    weights = prod_mean_net - eng_mean_net, # optional multiplier to adjust for readability
    edge_size_multiplier = edge_size_multiplier,
    edge_arrow_saturation_multiplier = edge_arrow_saturation_multiplier,
    node_position_multiplier = node_position_multiplier,
    edge_color = c("red","blue")) |>
  nodes(
    node_size_multiplier = node_size_multiplier,
    node_position_multiplier = node_position_multiplier,
    self_connection_color = c("red","blue"))

plot(set_2, title = "Product Designer vs ServiceDesigner") |>
  units(
    points = prod_pts, 
    points_color = "red",
    show_mean = TRUE, show_points = FALSE, with_ci = TRUE) |>
  units(
    points =serv_pts, 
    points_color = "green",
    show_mean = TRUE, show_points = FALSE, with_ci = TRUE) |>
  edges(
    weights = prod_mean_net - serv_mean_net, # optional multiplier to adjust for readability
    edge_size_multiplier = edge_size_multiplier,
    edge_arrow_saturation_multiplier = edge_arrow_saturation_multiplier,
    node_position_multiplier = node_position_multiplier,
    edge_color = c("red","green")) |>
  nodes(
    node_size_multiplier = node_size_multiplier,
    node_position_multiplier = node_position_multiplier,
    self_connection_color = c("red","green"))

plot(set_2, title = "Service Designer vs Engineer") |>
  units(
    points = serv_pts, 
    points_color = "green",
    show_mean = TRUE, show_points = FALSE, with_ci = TRUE) |>
  units(
    points = eng_pts, 
    points_color = "blue",
    show_mean = TRUE, show_points = FALSE, with_ci = TRUE) |>
  edges(
    weights = serv_mean_net - eng_mean_net, # optional multiplier to adjust for readability
    edge_size_multiplier = 1,
    edge_arrow_saturation_multiplier = edge_arrow_saturation_multiplier,
    node_position_multiplier = node_position_multiplier,
    edge_color = c("green","blue")) |>
  nodes(
    node_size_multiplier = node_size_multiplier,
    node_position_multiplier = node_position_multiplier,
    self_connection_color = c("green","blue"))

Plot 2: All Means


#get list of time phases and groups loop over or use map function

phases = unique(set_2$points$TimePhase)

groups = unique(set_2$points$Role)


col_list_2 = c("red",
              "blue",
              "green")

traces = c(2:10)

x_agency = plot(set_2, title = "Group Means by Phase -- Agency")
count = 1

for (i in 1:length(phases)){
  for (j in 1:length(groups)){
    points = set_2$points %>% filter(TimePhase == phases[i], Role == groups[j])
    #print(head(points))
    x_agency = x_agency |>
      units(
        points = points,
        point_position_multiplier = point_position_multiplier,
        points_color = col_list_2[i],
        show_mean = TRUE, show_points = F, with_ci = FALSE
        ) |>
      nodes(node_size_multiplier = 0.3,
            node_position_multiplier = node_position_multiplier,
            self_connection_color = c("black"))|>
      plotly::layout(showlegend = TRUE, legend = list(x = 100, y = 0.9)) |>
      plotly::style(name = paste0(phases[i]," - ",groups[j]), traces = traces[count])
    count = count + 1
    
  }
}

x_agency

Check nesting

reg_dat_agency = set_2$points %>% filter(ENA_DIRECTION == "response")

ICC::ICCest(Speaker,SVD1,reg_dat_agency) #not significant

ICC::ICCest(Speaker,SVD2,reg_dat_agency) #significant we will need to include a variable for individual in the model
mod_x_agency = lm(SVD1 ~ as.factor(TimePhase) + Role, data = reg_dat_agency)
mod_y_agency = lm(SVD2 ~ as.factor(TimePhase) + Role, data = reg_dat_agency)


summary(mod_x_agency)
summary(mod_y_agency)

check for interactions: (interactions are significant so we should use those modes)

mod_x_agency_2 = lm(SVD1 ~ as.factor(TimePhase) + Role + as.factor(TimePhase)*Role, data = reg_dat_agency)
mod_y_agency_2 = lm(SVD2 ~ as.factor(TimePhase) + Role + as.factor(TimePhase)*Role, data = reg_dat_agency)

summary(mod_x_agency_2)
summary(mod_y_agency_2)

anova(mod_x_agency,mod_x_agency_2)
anova(mod_y_agency,mod_y_agency_2)

#Need to run mixed model for Y ##model is singular so stick with OLS

library(lmerTest)

mod_y_agency_mixed = lmerTest::lmer(SVD2 ~ 1 + (1|Speaker) + as.factor(TimePhase)*Role ,data = reg_dat_agency)

summary(mod_y_agency_mixed)

Marginal means x - RQ1

emm_ag1 = emmeans(mod_x_agency_2, specs = pairwise ~ Role, weights = "proportional")
print(emm_ag1$emmeans)
print(emm_ag1$contrasts)

Viewing interactions

emmip(mod_x_agency_2, Role ~ TimePhase)

Marginal means - x RQ2

emm_ag1 = emmeans(mod_x_agency_2, specs = pairwise ~ TimePhase|Role, weights = "proportional")
emm_ag1$contrasts

emm_ag2 = emmeans(mod_x_agency_2, specs = pairwise ~ Role|TimePhase, weights = "proportional")
emm_ag2$contrasts

Marginal means y - RQ1

emm_ag_y1 = emmeans(mod_y_agency_2, specs = pairwise ~ Role, weights = "proportional")
print(emm_ag_y1$emmeans)
print(emm_ag_y1$contrasts)

Viewing interactions

emmip(mod_y_agency_2, Role ~ TimePhase)

Marginal means - y RQ2

emm_ag_y1 = emmeans(mod_y_agency_2, specs = pairwise ~ TimePhase|Role, weights = "proportional")
emm_ag_y1$contrasts

emm_ag_y2 = emmeans(mod_y_agency_2, specs = pairwise ~ Role|TimePhase, weights = "proportional")
emm_ag_y2$contrasts

Calculate eff sizes

#to do

Model diagnostics

check_model(mod_x_agency_2)
check_model(mod_y_agency_2)

Plot network subtractions

mean1 = set_2$points %>% dplyr::filter(TimePhase == 1, Role == "Engineer")
mean2 = set_2$points %>% dplyr::filter(TimePhase == 1, Role == "ProductDesigner")

mean1_net = set_2$line.weights %>% dplyr::filter(TimePhase == 1, Role == "Engineer") %>% colMeans()
mean2_net = set_2$line.weights %>% dplyr::filter(TimePhase == 1, Role == "ProductDesigner") %>% colMeans()

plot(set_2, title = "Network subtraction") |>
  units(
    points = mean1, 
    points_color = "red",
    show_mean = TRUE, show_points = FALSE, with_ci = TRUE) |>
  units(
    points = mean2, 
    points_color = "blue",
    show_mean = TRUE, show_points = FALSE, with_ci = TRUE) |>
  edges(
    weights = mean1_net - mean2_net, # optional multiplier to adjust for readability
    edge_size_multiplier = edge_size_multiplier,
    edge_arrow_saturation_multiplier = edge_arrow_saturation_multiplier,
    node_position_multiplier = node_position_multiplier,
    edge_color = c("red","blue")) |>
  nodes(
    node_size_multiplier = node_size_multiplier,
    node_position_multiplier = node_position_multiplier,
    self_connection_color = c("red","blue"))
LS0tCnRpdGxlOiAiSkxBLU9OQS0yMDIzIgphdXRob3I6ICJaYWNoICYgWXVhbnJ1IgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKICBwZGZfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHllcwogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogICAgZGZfcHJpbnQ6IHBhZ2VkCmVkaXRvcl9vcHRpb25zOgogIG1hcmtkb3duOgogICAgd3JhcDogc2VudGVuY2UKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1UUlVFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpCmBgYAoKYGBge3J9CnJtKGxpc3QgPSBscygpKQpgYGAKCmBgYHtyfQojaW5zdGFsbC5wYWNrYWdlcygib25hIiwgcmVwb3MgPSBjKCJodHRwczovL2NyYW4ucWUtbGlicy5vcmciLCAiaHR0cHM6Ly9jcmFuLnJzdHVkaW8ub3JnIikpICMgb25seSBydW4gb25jZQojaW5zdGFsbC5wYWNrYWdlcygidG1hIiwgcmVwb3MgPSBjKCJodHRwczovL2NyYW4ucWUtbGlicy5vcmciLCAiaHR0cHM6Ly9jcmFuLnJzdHVkaW8ub3JnIikpICMgb25seSBydW4gb25jZQpgYGAKCmBgYHtyIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkob25hKQpsaWJyYXJ5KHRtYSkKbGlicmFyeShtYWdyaXR0cikKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZW1tZWFucykKbGlicmFyeShwZXJmb3JtYW5jZSkKYGBgCgptb3N0IHJlY2VudCBkYXRhIEF5YW5vIHNoYXJlZApgYGB7cn0KZGF0YSA8LSByZWFkLmNzdigifi9ScHJvamVjdHMvYXlhbm8vUEVTXzAxMHY2KHNlbGVjdGVkKS5jc3YiKQpgYGAKCmBgYHtyfQp1bml0cyA8LSBjKCJTcGVha2VyIiwgIlJvbGUiLCAiVGltZVBoYXNlIikKCmNvZGVzXzEgPC0gYygiRnVuY3Rpb25zIiwgIkFlc3RoZXRpY3MiLCAiVXNlciIsICJWaXNpb24iLCAiUHJvdG90eXBpbmciKSAjIGRlc2lnbiBhY3Rpb25zIGNvZGVzCmNvZGVzXzIgPC0gYygiQ0EiLCAiQUxvSyIsICJDU1UiLCAiR0NBIiwgIlByb2plY3RpdmUiLCJSZWd1bGF0aXZlIiwiUmVsYXRpb25hbCIpICMgc2hhcmVkIGVwaXN0ZW1pYyBhZ2VuY3kgY29kZXMKCmhvb19ydWxlcyA8LSBjb252ZXJzYXRpb25fcnVsZXMoCiAgKFRpbWVQaGFzZSAlaW4lIFVOSVQkVGltZVBoYXNlICYgUm9sZSAlaW4lIFVOSVQkUm9sZSkKKQpgYGAKCm5vdGVzOiBhY2N1bV8xIGFuZCBzZXRfMSBhcmUgZm9yIGRlc2lnbiBhY3Rpb24gY29kZXM7IGFjY3VtXzIgYW5kIHNldF8yIGFyZSBmb3Igc2hhcmVkIGVwaXN0ZW1pYyBhZ2VuY3kgY29kZXMKCmBgYHtyfQphY2N1bV8xIDwtCiAgY29udGV4dHMoZGF0YSwgCiAgICAgICAgICAgdW5pdHNfYnkgPSB1bml0cywgCiAgICAgICAgICAgaG9vX3J1bGVzID0gaG9vX3J1bGVzKSAlPiUKICBhY2N1bXVsYXRlX2NvbnRleHRzKGNvZGVzID0gY29kZXNfMSwgCiAgICAgICAgICAgICAgICAgICAgICBkZWNheS5mdW5jdGlvbiA9IGRlY2F5KHNpbXBsZV93aW5kb3csIHdpbmRvd19zaXplID0gNCksCiAgICAgICAgICAgICAgICAgICAgICByZXR1cm4uZW5hLnNldCA9IEZBTFNFLCBub3JtLmJ5ID0gTlVMTCkKYGBgCgpOb3RlOiBOb3QgZG9pbmcgbWVhbnMgcm90YXRpb24gc28gSSBjYW4gY29tcGFyZSBldmVyeXRoaW5nIGluIHRoZSBzYW1lIHNwYWNlCgpgYGB7cn0Kc2V0XzEgPC0KICAjIG1vZGVsKGFjY3VtXzEsCiAgIyAgICAgICByb3RhdGUudXNpbmcgPSAibWVhbiIsCiAgIyAgICAgICByb3RhdGlvbi5wYXJhbXMgPSAKICAjICAgICAgICAgbGlzdChlbmdpbmVlcnM9YWNjdW1fMSRtZXRhLmRhdGEkUm9sZT09IkVuZ2luZWVyIiwKICAjICAgICAgICAgICAgICBzZXJ2aWNlZGVzaWduZXJzPWFjY3VtXzEkbWV0YS5kYXRhJFJvbGU9PSJTZXJ2aWNlRGVzaWduZXIiKSkKICAKICBtb2RlbChhY2N1bV8xKQpgYGAKCmBgYHtyfQphY2N1bV8yIDwtCiAgY29udGV4dHMoZGF0YSwgCiAgICAgICAgICAgdW5pdHNfYnkgPSB1bml0cywgCiAgICAgICAgICAgaG9vX3J1bGVzID0gaG9vX3J1bGVzKSAlPiUKICBhY2N1bXVsYXRlX2NvbnRleHRzKGNvZGVzID0gY29kZXNfMiwgCiAgICAgICAgICAgICAgICAgICAgICBkZWNheS5mdW5jdGlvbiA9IGRlY2F5KHNpbXBsZV93aW5kb3csIHdpbmRvd19zaXplID0gNCksCiAgICAgICAgICAgICAgICAgICAgICByZXR1cm4uZW5hLnNldCA9IEZBTFNFLCBub3JtLmJ5ID0gTlVMTCkKYGBgCgpgYGB7cn0Kc2V0XzIgPC0KICAjIG1vZGVsKGFjY3VtXzIsCiAgIyAgICAgICByb3RhdGUudXNpbmcgPSAibWVhbiIsCiAgIyAgICAgICByb3RhdGlvbi5wYXJhbXMgPSAKICAjICAgICAgICAgbGlzdChlbmdpbmVlcnM9YWNjdW1fMiRtZXRhLmRhdGEkUm9sZT09IkVuZ2luZWVyIiwKICAjICAgICAgICAgICAgICBzZXJ2aWNlZGVzaWduZXJzPWFjY3VtXzIkbWV0YS5kYXRhJFJvbGU9PSJTZXJ2aWNlRGVzaWduZXIiKSkKICAKICBtb2RlbChhY2N1bV8yKQpgYGAKCmdsb2JhbCB2aXN1YWwgcGFyYW1ldGVyIChsZXQncyBtYWtlIHN1cmUgYWxsIHRoZSBwbG90cyB1c2UgdGhlIHNhbWUgbGV2ZWwgb2YgbXVsdGlwbGllcikKYGBge3J9Cm5vZGVfc2l6ZV9tdWx0aXBsaWVyID0gMC4zICMgc2NhbGUgdXAgb3IgZG93biBub2RlIHNpemVzCm5vZGVfcG9zaXRpb25fbXVsdGlwbGllciA9IDEgIyB6b29tIGluIG9yIG91dCBub2RlIHBvc2l0aW9ucwpwb2ludF9wb3NpdGlvbl9tdWx0aXBsaWVyID0gMSAjIHpvb20gaW4gb3Igb3V0IHRoZSBwb2ludCBwb3NpdGlvbnMKZWRnZV9hcnJvd19zYXR1cmF0aW9uX211bHRpcGxpZXIgPSAxLjUgIyBhZGp1c3QgdGhlIGNoZXZyb24gY29sb3IgbGlnaHRlciBvciBkYXJrZXIKZWRnZV9zaXplX211bHRpcGxpZXIgPSAxICMgc2NhbGUgdXAgb3IgZG93biBlZGdlIHNpemVzCmBgYAoKTW9kZWwgMTogZGVzaWduIGFjdGlvbiBjb2RlcwoKUGxvdCAxYTogT3ZlcmFsbCBHcm91cCBDb21wYXJpc29ucwpgYGB7cn0KdHJhY2VzID0gYygyOjEwKQpwbG90KHNldF8xLCB0aXRsZSA9ICJHcm91cHMiKSB8PgogIHVuaXRzKAogICAgcG9pbnRzPSBzZXRfMSRwb2ludHMkUm9sZSRQcm9kdWN0RGVzaWduZXIsIAogICAgcG9pbnRfcG9zaXRpb25fbXVsdGlwbGllciA9IHBvaW50X3Bvc2l0aW9uX211bHRpcGxpZXIsCiAgICBwb2ludHNfY29sb3IgPSBjKCJyZWQiKSwKICAgIHNob3dfbWVhbiA9IFRSVUUsIHNob3dfcG9pbnRzID0gRkFMU0UsIHdpdGhfY2kgPSBUUlVFKSB8PgogICB1bml0cygKICAgIHBvaW50cz0gc2V0XzEkcG9pbnRzJFJvbGUkRW5naW5lZXIsIAogICAgcG9pbnRfcG9zaXRpb25fbXVsdGlwbGllciA9IHBvaW50X3Bvc2l0aW9uX211bHRpcGxpZXIsCiAgICBwb2ludHNfY29sb3IgPSBjKCJibHVlIiksCiAgICBzaG93X21lYW4gPSBUUlVFLCBzaG93X3BvaW50cyA9IEZBTFNFLCB3aXRoX2NpID0gVFJVRSkgfD4KICAgdW5pdHMoCiAgICBwb2ludHM9IHNldF8xJHBvaW50cyRSb2xlJFNlcnZpY2VEZXNpZ25lciwgCiAgICBwb2ludF9wb3NpdGlvbl9tdWx0aXBsaWVyID0gcG9pbnRfcG9zaXRpb25fbXVsdGlwbGllciwKICAgIHBvaW50c19jb2xvciA9IGMoImdyZWVuIiksCiAgICBzaG93X21lYW4gPSBUUlVFLCBzaG93X3BvaW50cyA9IEZBTFNFLCB3aXRoX2NpID0gVFJVRSkgfD4KICBub2Rlcyhub2RlX3NpemVfbXVsdGlwbGllciA9IDAuMywKICAgICAgICAgICAgbm9kZV9wb3NpdGlvbl9tdWx0aXBsaWVyID0gbm9kZV9wb3NpdGlvbl9tdWx0aXBsaWVyLAogICAgICAgICAgICBzZWxmX2Nvbm5lY3Rpb25fY29sb3IgPSBjKCJibGFjayIpKXw+CiAgICAgIHBsb3RseTo6bGF5b3V0KHNob3dsZWdlbmQgPSBUUlVFLCBsZWdlbmQgPSBsaXN0KHggPSAxMDAsIHkgPSAwLjkpKSB8PgogICAgICBwbG90bHk6OnN0eWxlKG5hbWUgPSAiUHJvZHVjdCBEZXNpZ25lciIsIHRyYWNlcyA9IHRyYWNlc1sxXSkgfD4KICAgICAgcGxvdGx5OjpzdHlsZShuYW1lID0gIkVuZ2luZWVyIiwgdHJhY2VzID0gdHJhY2VzWzJdKSB8PgogICAgICBwbG90bHk6OnN0eWxlKG5hbWUgPSAiU2VydmljZSBEZXNpZ25lciIsIHRyYWNlcyA9IHRyYWNlc1szXSkKICAKYGBgClBsb3QgMWI6IEdyb3VwIHN1YnRyYWN0aW9ucwpgYGB7cn0KcHJvZF9wdHMgPSBzZXRfMSRwb2ludHMkUm9sZSRQcm9kdWN0RGVzaWduZXIgCmVuZ19wdHMgPSBzZXRfMSRwb2ludHMkUm9sZSRFbmdpbmVlcgpzZXJ2X3B0cyA9IHNldF8xJHBvaW50cyRSb2xlJFNlcnZpY2VEZXNpZ25lcgoKcHJvZF9tZWFuX25ldCA9IHNldF8xJGxpbmUud2VpZ2h0cyAlPiUgZHBseXI6OmZpbHRlcihSb2xlID09ICJQcm9kdWN0RGVzaWduZXIiKSAlPiUgY29sTWVhbnMoKQplbmdfbWVhbl9uZXQgPSBzZXRfMSRsaW5lLndlaWdodHMgJT4lIGRwbHlyOjpmaWx0ZXIoUm9sZSA9PSAiRW5naW5lZXIiKSAlPiUgY29sTWVhbnMoKQpzZXJ2X21lYW5fbmV0ID0gc2V0XzEkbGluZS53ZWlnaHRzICU+JSBkcGx5cjo6ZmlsdGVyKFJvbGUgPT0gIlNlcnZpY2VEZXNpZ25lciIpICU+JSBjb2xNZWFucygpCgpwbG90KHNldF8xLCB0aXRsZSA9ICJQcm9kdWN0IERlc2lnbmVyIHZzIEVuZ2luZWVyIikgfD4KICB1bml0cygKICAgIHBvaW50cyA9IHByb2RfcHRzLCAKICAgIHBvaW50c19jb2xvciA9ICJyZWQiLAogICAgc2hvd19tZWFuID0gVFJVRSwgc2hvd19wb2ludHMgPSBGQUxTRSwgd2l0aF9jaSA9IFRSVUUpIHw+CiAgdW5pdHMoCiAgICBwb2ludHMgPSBlbmdfcHRzLCAKICAgIHBvaW50c19jb2xvciA9ICJibHVlIiwKICAgIHNob3dfbWVhbiA9IFRSVUUsIHNob3dfcG9pbnRzID0gRkFMU0UsIHdpdGhfY2kgPSBUUlVFKSB8PgogIGVkZ2VzKAogICAgd2VpZ2h0cyA9IHByb2RfbWVhbl9uZXQgLSBlbmdfbWVhbl9uZXQsICMgb3B0aW9uYWwgbXVsdGlwbGllciB0byBhZGp1c3QgZm9yIHJlYWRhYmlsaXR5CiAgICBlZGdlX3NpemVfbXVsdGlwbGllciA9IGVkZ2Vfc2l6ZV9tdWx0aXBsaWVyLAogICAgZWRnZV9hcnJvd19zYXR1cmF0aW9uX211bHRpcGxpZXIgPSBlZGdlX2Fycm93X3NhdHVyYXRpb25fbXVsdGlwbGllciwKICAgIG5vZGVfcG9zaXRpb25fbXVsdGlwbGllciA9IG5vZGVfcG9zaXRpb25fbXVsdGlwbGllciwKICAgIGVkZ2VfY29sb3IgPSBjKCJyZWQiLCJibHVlIikpIHw+CiAgbm9kZXMoCiAgICBub2RlX3NpemVfbXVsdGlwbGllciA9IG5vZGVfc2l6ZV9tdWx0aXBsaWVyLAogICAgbm9kZV9wb3NpdGlvbl9tdWx0aXBsaWVyID0gbm9kZV9wb3NpdGlvbl9tdWx0aXBsaWVyLAogICAgc2VsZl9jb25uZWN0aW9uX2NvbG9yID0gYygicmVkIiwiYmx1ZSIpKQoKcGxvdChzZXRfMSwgdGl0bGUgPSAiUHJvZHVjdCBEZXNpZ25lciB2cyBTZXJ2aWNlRGVzaWduZXIiKSB8PgogIHVuaXRzKAogICAgcG9pbnRzID0gcHJvZF9wdHMsIAogICAgcG9pbnRzX2NvbG9yID0gInJlZCIsCiAgICBzaG93X21lYW4gPSBUUlVFLCBzaG93X3BvaW50cyA9IEZBTFNFLCB3aXRoX2NpID0gVFJVRSkgfD4KICB1bml0cygKICAgIHBvaW50cyA9c2Vydl9wdHMsIAogICAgcG9pbnRzX2NvbG9yID0gImdyZWVuIiwKICAgIHNob3dfbWVhbiA9IFRSVUUsIHNob3dfcG9pbnRzID0gRkFMU0UsIHdpdGhfY2kgPSBUUlVFKSB8PgogIGVkZ2VzKAogICAgd2VpZ2h0cyA9IHByb2RfbWVhbl9uZXQgLSBzZXJ2X21lYW5fbmV0LCAjIG9wdGlvbmFsIG11bHRpcGxpZXIgdG8gYWRqdXN0IGZvciByZWFkYWJpbGl0eQogICAgZWRnZV9zaXplX211bHRpcGxpZXIgPSBlZGdlX3NpemVfbXVsdGlwbGllciwKICAgIGVkZ2VfYXJyb3dfc2F0dXJhdGlvbl9tdWx0aXBsaWVyID0gZWRnZV9hcnJvd19zYXR1cmF0aW9uX211bHRpcGxpZXIsCiAgICBub2RlX3Bvc2l0aW9uX211bHRpcGxpZXIgPSBub2RlX3Bvc2l0aW9uX211bHRpcGxpZXIsCiAgICBlZGdlX2NvbG9yID0gYygicmVkIiwiZ3JlZW4iKSkgfD4KICBub2RlcygKICAgIG5vZGVfc2l6ZV9tdWx0aXBsaWVyID0gbm9kZV9zaXplX211bHRpcGxpZXIsCiAgICBub2RlX3Bvc2l0aW9uX211bHRpcGxpZXIgPSBub2RlX3Bvc2l0aW9uX211bHRpcGxpZXIsCiAgICBzZWxmX2Nvbm5lY3Rpb25fY29sb3IgPSBjKCJyZWQiLCJncmVlbiIpKQoKcGxvdChzZXRfMSwgdGl0bGUgPSAiU2VydmljZSBEZXNpZ25lciB2cyBFbmdpbmVlciIpIHw+CiAgdW5pdHMoCiAgICBwb2ludHMgPSBzZXJ2X3B0cywgCiAgICBwb2ludHNfY29sb3IgPSAiZ3JlZW4iLAogICAgc2hvd19tZWFuID0gVFJVRSwgc2hvd19wb2ludHMgPSBGQUxTRSwgd2l0aF9jaSA9IFRSVUUpIHw+CiAgdW5pdHMoCiAgICBwb2ludHMgPSBlbmdfcHRzLCAKICAgIHBvaW50c19jb2xvciA9ICJibHVlIiwKICAgIHNob3dfbWVhbiA9IFRSVUUsIHNob3dfcG9pbnRzID0gRkFMU0UsIHdpdGhfY2kgPSBUUlVFKSB8PgogIGVkZ2VzKAogICAgd2VpZ2h0cyA9IHNlcnZfbWVhbl9uZXQgLSBlbmdfbWVhbl9uZXQsICMgb3B0aW9uYWwgbXVsdGlwbGllciB0byBhZGp1c3QgZm9yIHJlYWRhYmlsaXR5CiAgICBlZGdlX3NpemVfbXVsdGlwbGllciA9IGVkZ2Vfc2l6ZV9tdWx0aXBsaWVyLAogICAgZWRnZV9hcnJvd19zYXR1cmF0aW9uX211bHRpcGxpZXIgPSBlZGdlX2Fycm93X3NhdHVyYXRpb25fbXVsdGlwbGllciwKICAgIG5vZGVfcG9zaXRpb25fbXVsdGlwbGllciA9IG5vZGVfcG9zaXRpb25fbXVsdGlwbGllciwKICAgIGVkZ2VfY29sb3IgPSBjKCJncmVlbiIsImJsdWUiKSkgfD4KICBub2RlcygKICAgIG5vZGVfc2l6ZV9tdWx0aXBsaWVyID0gbm9kZV9zaXplX211bHRpcGxpZXIsCiAgICBub2RlX3Bvc2l0aW9uX211bHRpcGxpZXIgPSBub2RlX3Bvc2l0aW9uX211bHRpcGxpZXIsCiAgICBzZWxmX2Nvbm5lY3Rpb25fY29sb3IgPSBjKCJncmVlbiIsImJsdWUiKSkKYGBgClBsb3QgMjogQWxsIE1lYW5zIGJ5IHBoYXNlCmBgYHtyfQoKI2dldCBsaXN0IG9mIHRpbWUgcGhhc2VzIGFuZCBncm91cHMgbG9vcCBvdmVyIG9yIHVzZSBtYXAgZnVuY3Rpb24KCnBoYXNlcyA9IHVuaXF1ZShzZXRfMSRwb2ludHMkVGltZVBoYXNlKQoKZ3JvdXBzID0gdW5pcXVlKHNldF8xJHBvaW50cyRSb2xlKQoKY29sX2xpc3RfMiA9IGMoInJlZCIsI3BoYXNlIDEKICAgICAgICAgICAgICAiYmx1ZSIsICNwaGFzZSAyCiAgICAgICAgICAgICAgImdyZWVuIikgI3BoYXNlIDMKCnRyYWNlcyA9IGMoMjoxMCkKCnggPSBwbG90KHNldF8xLCB0aXRsZSA9ICJHcm91cCBNZWFucyBieSBQaGFzZSIpCmNvdW50ID0gMQpmb3IgKGkgaW4gMTpsZW5ndGgocGhhc2VzKSl7CiAgZm9yIChqIGluIDE6bGVuZ3RoKGdyb3VwcykpewogICAgcG9pbnRzID0gc2V0XzEkcG9pbnRzICU+JSBmaWx0ZXIoVGltZVBoYXNlID09IHBoYXNlc1tpXSwgUm9sZSA9PSBncm91cHNbal0pCiAgICB4ID0geCB8PgogICAgICB1bml0cygKICAgICAgICBwb2ludHMgPSBwb2ludHMsCiAgICAgICAgcG9pbnRfcG9zaXRpb25fbXVsdGlwbGllciA9IHBvaW50X3Bvc2l0aW9uX211bHRpcGxpZXIsCiAgICAgICAgcG9pbnRzX2NvbG9yID0gY29sX2xpc3RfMltpXSwKICAgICAgICBzaG93X21lYW4gPSBUUlVFLCBzaG93X3BvaW50cyA9IEYsIHdpdGhfY2kgPSBGQUxTRQogICAgICAgICkgfD4KICAgICAgbm9kZXMobm9kZV9zaXplX211bHRpcGxpZXIgPSAwLjMsCiAgICAgICAgICAgIG5vZGVfcG9zaXRpb25fbXVsdGlwbGllciA9IG5vZGVfcG9zaXRpb25fbXVsdGlwbGllciwKICAgICAgICAgICAgc2VsZl9jb25uZWN0aW9uX2NvbG9yID0gYygiYmxhY2siKSl8PgogICAgICBwbG90bHk6OmxheW91dChzaG93bGVnZW5kID0gVFJVRSwgbGVnZW5kID0gbGlzdCh4ID0gMTAwLCB5ID0gMC45KSkgfD4KICAgICAgcGxvdGx5OjpzdHlsZShuYW1lID0gcGFzdGUwKHBoYXNlc1tpXSwiIC0gIixncm91cHNbal0pLCB0cmFjZXMgPSB0cmFjZXNbY291bnRdKQogICAgY291bnQgPSBjb3VudCArIDEKICB9Cn0KCngKCmBgYAoKU3RhdGlzdGljYWwgVGVzdHM6CgpJbiB0aGVzZSBkYXRhLCB0aGUgb2JzZXJ2YXRpb25zIGFyZSBuZXN0ZWQgd2l0aGluIHBhcnRpY2lwYW50cywgc28gd2UgbmVlZCB0byBjaGVjayBpZiB0aGlzIG5lc3RpbmcgCmhhcyBhIHNpZ25pZmljYW50IGVmZmVjdC4gV2UgZG8gdGhpcyBieSBjb25zdHJ1Y3RpbmcgYSBjb25maWRlbmNlIGludGVydmFsCmFyb3VuZCB0aGUgaW50cmFjbGFzcyBjb3JyZWxhdGlvbiBjb2VmZmljaWVudCAoaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSW50cmFjbGFzc19jb3JyZWxhdGlvbikuIElmIHRoZSBpbnRlcnZhbCBjb250YWlucyB6ZXJvLCBuZXN0aW5nIGlzIG5vdCBzaWduaWZpY2FudC4KCmBgYHtyfQpyZWdfZGF0ID0gc2V0XzEkcG9pbnRzICU+JSBmaWx0ZXIoRU5BX0RJUkVDVElPTiA9PSAicmVzcG9uc2UiKQoKSUNDOjpJQ0Nlc3QoU3BlYWtlcixTVkQxLHJlZ19kYXQpICNub3Qgc2lnbmlmaWNhbnQKCklDQzo6SUNDZXN0KFNwZWFrZXIsU1ZEMixyZWdfZGF0KSAjbm90IHNpZ25pZmljYW50CgoKYGBgCgpOZXN0aW5nIGlzIG5vdCBzaWduaWZpY2FudCBzbyB3ZSBwcm9jZWVkIHdpdGggYW4gT0xTIHJlZ3Jlc3Npb24uIEJlbG93IHdlIHNldCB1cCB0d28gbW9kZWxzIGZvciBlYWNoIGRpbWVuc2lvbiBhbmQgdGVzdCB3aGV0aGVyIGluY2x1ZGluZyBpbnRlcmFjdGlvbiBlZmZlY3RzIGluIHRoZSBhbmFseXNpcyBzaWduaWZpY2FudGx5IGltcHJvdmVzIHRoZSBtb2Rlcy4KCmBgYHtyfQptb2RfeCA9IGxtKFNWRDEgfiBhcy5mYWN0b3IoVGltZVBoYXNlKSArIFJvbGUsIGRhdGEgPSByZWdfZGF0KQptb2RfeSA9IGxtKFNWRDIgfiBhcy5mYWN0b3IoVGltZVBoYXNlKSArIFJvbGUsIGRhdGEgPSByZWdfZGF0KQoKbW9kX3hfMiA9IGxtKFNWRDEgfiBhcy5mYWN0b3IoVGltZVBoYXNlKSpSb2xlLCBkYXRhID0gcmVnX2RhdCkKYW5vdmEobW9kX3gsbW9kX3hfMikKCm1vZF95XzIgPSBsbShTVkQyIH4gYXMuZmFjdG9yKFRpbWVQaGFzZSkqUm9sZSwgZGF0YSA9IHJlZ19kYXQpCmFub3ZhKG1vZF95LG1vZF95XzIpCgpgYGAKSW50ZXJhY3Rpb25zIGFyZSBzaWduaWZpY2FudCwgc28gd2Ugc2hvdWxkIHVzZSB0aGUgaW50ZXJhY3Rpb24gbW9kZWxzLiBMZXQncyB2aWV3IHRob3NlIG1vZGVscwoKYGBge3J9CnN1bW1hcnkobW9kX3hfMikKc3VtbWFyeShtb2RfeV8yKQpgYGAKVmlld2luZyBpbnRlcmFjdGlvbnMKYGBge3J9CmVtbWlwKG1vZF94XzIsIFJvbGUgfiBUaW1lUGhhc2UpCmVtbWlwKG1vZF95XzIsIFJvbGUgfiBUaW1lUGhhc2UpCmBgYApXaGVuIGludGVyYWN0aW9ucyBhcmUgaW50cm9kdWNlZCwgaW50ZXJwcmV0aW5nIHJlZ3Jlc3Npb24gY29lZmZpY2llbnRzIGJlY29tZXMgbW9yZSAKZGlmZmljdWx0LCBzbyB3ZSBjYWxjdWxhdGVkIHRoZSBtYXJnaW5hbCBtZWFucyBhbmQgdmFyaW91cyBjb250cmFzdHMgKGkuZS4sIGNvbXBhcmlzb25zIGJldHdlZW4gZ3JvdXBzIG9mIGludGVyZXN0KSB0byBhZGRyZXNzIG91ciByZXNlYXJjaCBxdWVzdGlvbnMuCgpSUTEgKFggZGltZW5zaW9uIC0gRGVzaWduIEFjdGlvbnMpOiBIZXJlIHdlIHdhbnQgdG8gY29tcGFyZSB0aGUgIm1haW4gZWZmZWN0IiBvZiBSb2xlIG9uIHRoZSB4IGRpbWVuc2lvbi0tLWkuZS4sIGFyZSB0aGVyZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIHRoZSByb2xlcyBvbiB0aGUgWCBkaW1lbnNpb24gd2hlbiBhdmVyYWdpbmcgb3ZlciBUaW1lUGhhc2VzLgoKYGBge3J9CmVtbV94MSA9IGVtbWVhbnMobW9kX3hfMiwgc3BlY3MgPSBwYWlyd2lzZSB+IFJvbGUsIHdlaWdodHMgPSAicHJvcG9ydGlvbmFsIikKcHJpbnQoZW1tX3gxJGNvbnRyYXN0cykKYGBgCk9ubHkgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZSBvbiB0aGUgWCBpcyBiZXR3ZWVuIEVuZ2luZWVyIGFuZCBTZXJ2aWNlIGRlc2lnbmVyLiBMZXQncyBjYWxjdWxhdGUgdGhlIGVmZmVjdCBzaXplIChkaWZmZXJlbmNlIGluIHN0YW5kYXJkIGRldmlhdGlvbnMpIG9mIHRoYXQgZGlmZmVyZW5jZS4gV2Ugd2lsbCB1c2UgQ29oZW4ncyBkLgoKYGBge3J9CmNvaGVuc2QgPSBmdW5jdGlvbihkaWZmXyxnMSxnMil7CiAgZGlmZl8vKHNxcnQoKHNkKGcxKV4yICsgc2QoZzIpXjIpLzIpKQp9Cgpjb250cmFzdHMgPSBhc190aWJibGUoZW1tX3gxJGNvbnRyYXN0cykKZGlmZl8gPSBjb250cmFzdHMkZXN0aW1hdGVbMl0KZzEgPSByZWdfZGF0ICU+JSBmaWx0ZXIoUm9sZSA9PSAiRW5naW5lZXIiKSAlPiUgc2VsZWN0KFNWRDEpCmcyID0gcmVnX2RhdCAlPiUgZmlsdGVyKFJvbGUgPT0gIlNlcnZpY2VEZXNpZ25lciIpICU+JSBzZWxlY3QoU1ZEMSkKCmNvaGVuc2QoZGlmZl8gPSBkaWZmXyxnMSA9IGcxJFNWRDEsZzIgPSBnMiRTVkQxKQoKYGBgCgpSUTEgKFkgZGltZW5zaW9uIC0gRGVzaWduIEFjdGlvbnMpOiBIZXJlIHdlIHdhbnQgdG8gY29tcGFyZSB0aGUgIm1haW4gZWZmZWN0IiBvZiBSb2xlIG9uIHRoZSB5IGRpbWVuc2lvbi0tLWkuZS4sIGFyZSB0aGVyZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIHRoZSByb2xlcyBvbiB0aGUgWCBkaW1lbnNpb24gd2hlbiBhdmVyYWdpbmcgb3ZlciBUaW1lUGhhc2VzLgoKYGBge3J9CmVtbV95MSA9IGVtbWVhbnMobW9kX3lfMiwgc3BlY3MgPSBwYWlyd2lzZSB+IFJvbGUsIHdlaWdodHMgPSAicHJvcG9ydGlvbmFsIikKcHJpbnQoZW1tX3kxJGNvbnRyYXN0cykKYGBgClNpZ25pZmljYW50IGRpZmZlcmVuY2VzIGJldHdlZW4gZW5naW5lZXIvcHJvZHVjdCBkZXNpZ25lciBhbmQgcHJvZHVjdGRlc2lnbmVyL3NlcnZpY2VkZXNpZ25lci4gTGV0J3MgZ2V0IHRoZSBlZmZlY3Qgc2l6ZXM6CgpgYGB7cn0KY29udHJhc3RzID0gYXNfdGliYmxlKGVtbV95MSRjb250cmFzdHMpCgpkaWZmX2V2cCA9IGNvbnRyYXN0cyRlc3RpbWF0ZVsxXQpnMSA9IHJlZ19kYXQgJT4lIGZpbHRlcihSb2xlID09ICJFbmdpbmVlciIpICU+JSBzZWxlY3QoU1ZEMSkKZzIgPSByZWdfZGF0ICU+JSBmaWx0ZXIoUm9sZSA9PSAiUHJvZHVjdERlc2lnbmVyIikgJT4lIHNlbGVjdChTVkQxKQoKZF9ldnAgPSBjb2hlbnNkKGRpZmZfID0gZGlmZl8sZzEgPSBnMSRTVkQxLGcyID0gZzIkU1ZEMSkKCmRpZmZfcHZzID0gY29udHJhc3RzJGVzdGltYXRlWzNdCmcxID0gcmVnX2RhdCAlPiUgZmlsdGVyKFJvbGUgPT0gIlByb2R1Y3REZXNpZ25lciIpICU+JSBzZWxlY3QoU1ZEMSkKZzIgPSByZWdfZGF0ICU+JSBmaWx0ZXIoUm9sZSA9PSAiU2VydmljZURlc2lnbmVyIikgJT4lIHNlbGVjdChTVkQxKQoKZF9wdnMgPSBjb2hlbnNkKGRpZmZfID0gZGlmZl8sZzEgPSBnMSRTVkQxLGcyID0gZzIkU1ZEMSkKCmRfZXZwCmRfcHZzCmBgYAoKTWFyZ2luYWwgbWVhbnMgLSB4IFJRMgoKCkhlcmUgd2UgdXNlIG1hcmdpbmFsIG1lYW5zIHRvIHRlc3QgZm9yIGRpZmZlcmVuY2VzIGJldHdlZW4gdGltZXBoYXNlcyB3aXRoaW4gZ3JvdXBzIGFuZCBncm91cHMgd2l0aGluIHRpbWVwaGFzZSBhbmQgCgpgYGB7cn0KbGlicmFyeShlbW1lYW5zKQoKZW1tX3gxYSA9IGVtbWVhbnMobW9kX3hfMiwgc3BlY3MgPSBwYWlyd2lzZSB+IFRpbWVQaGFzZXxSb2xlLCB3ZWlnaHRzID0gInByb3BvcnRpb25hbCIpICN0aW1lcGhhc2VzIHcvbiBncm91cHMKZW1tX3gxYSA9IGFzX3RpYmJsZShlbW1feDFhJGNvbnRyYXN0cykKCmVtbV94MiA9IGVtbWVhbnMobW9kX3hfMiwgc3BlY3MgPSBwYWlyd2lzZSB+IFJvbGV8VGltZVBoYXNlLCB3ZWlnaHRzID0gInByb3BvcnRpb25hbCIpICNncm91cHMgdy9uIHRpbWVwaGFzZXMKZW1tX3gyID0gYXNfdGliYmxlKGVtbV94MiRjb250cmFzdHMpCgojc2VlIGhlcmU6IGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9lbW1lYW5zL3ZpZ25ldHRlcy9pbnRlcmFjdGlvbnMuaHRtbAoKZW1tX3gxYSA9IGVtbV94MWEgJT4lIGZpbHRlcihwLnZhbHVlIDwgMC4wNSkKZW1tX3gyID0gZW1tX3gyICU+JSBmaWx0ZXIocC52YWx1ZSA8IDAuMDUpCgplbW1feDFhCmVtbV94MgoKYGBgClNldmVyYWwgY29udHJhc3RzIGFyZSBzaWduaWZpY2FudC4gTGV0J3MgY2FsY3VsYXRlIHRoZSBlZmZlY3Qgc2l6ZXMKYGBge3J9CmNvaGVuc2RfMiA9IGZ1bmN0aW9uKGRpZmZfLCBzZDEsIHNkMil7CiAgY2QgPSBkaWZmXy8oc3FydCgoc2QxXjIgKyBzZDJeMikvMikpCiAgI3ByaW50KHNxcnQoKHNkMV4yICsgc2QyXjIpLzIpKQogICNwcmludChkaWZmXykKICByZXR1cm4oY2QpCn0KCgpzZHMueCA9IHJlZ19kYXQgJT4lIGdyb3VwX2J5KFJvbGUsIGFzLmZhY3RvcihUaW1lUGhhc2UpKSAlPiUgc3VtbWFyaXNlKHN0ZGV2ID0gc2QoU1ZEMSkpCgojdGltZXBoYXNlcyB3L24gZ3JvdXBzCmVuZ190MXQyID0gY29oZW5zZF8yKGVtbV94MWEkZXN0aW1hdGVbMV0sc2QxID0gc2RzLngkc3RkZXZbMV0sIHNkMiA9IHNkcy54JHN0ZGV2WzJdKSAjIyNGSVgKZW5nX3QxdDMgPSBjb2hlbnNkXzIoZW1tX3gxYSRlc3RpbWF0ZVsyXSxzZDEgPSBzZHMueCRzdGRldlsxXSwgc2QyID0gc2RzLngkc3RkZXZbM10pCnBkX3QxdDIgPSBjb2hlbnNkXzIoZW1tX3gxYSRlc3RpbWF0ZVszXSxzZDEgPSBzZHMueCRzdGRldls0XSwgc2QyID0gc2RzLngkc3RkZXZbNV0pCnBkX3QxdDMgPSBjb2hlbnNkXzIoZW1tX3gxYSRlc3RpbWF0ZVs0XSxzZDEgPSBzZHMueCRzdGRldls0XSwgc2QyID0gc2RzLngkc3RkZXZbNl0pCnNkX3QxdDMgPSBjb2hlbnNkXzIoZW1tX3gxYSRlc3RpbWF0ZVs1XSxzZDEgPSBzZHMueCRzdGRldls3XSwgc2QyID0gc2RzLngkc3RkZXZbOV0pCnNkX3QydDMgPSBjb2hlbnNkXzIoZW1tX3gxYSRlc3RpbWF0ZVs2XSxzZDEgPSBzZHMueCRzdGRldls4XSwgc2QyID0gc2RzLngkc3RkZXZbOV0pCgpwcmludChsaXN0KGVuZ190MXQyLGVuZ190MXQzLHBkX3QxdDIscGRfdDF0MyxzZF90MXQzLHNkX3QydDMpKSAKCgojZ3JvdXBzIHcvbiB0aW1lcGhhcwp0MV9ldnAgPSBjb2hlbnNkXzIoZW1tX3gyJGVzdGltYXRlWzFdLCBzZDEgPSBzZHMueCRzdGRldlsxXSxzZDIgPSBzZHMueCRzdGRldls0XSkKdDFfZXZzID0gY29oZW5zZF8yKGVtbV94MiRlc3RpbWF0ZVsyXSwgc2QxID0gc2RzLngkc3RkZXZbMV0sc2QyID0gc2RzLngkc3RkZXZbN10pCnQyX2V2cyA9IGNvaGVuc2RfMihlbW1feDIkZXN0aW1hdGVbM10sIHNkMSA9IHNkcy54JHN0ZGV2WzJdLHNkMiA9IHNkcy54JHN0ZGV2WzhdKQp0Ml9wdnMgPSBjb2hlbnNkXzIoZW1tX3gyJGVzdGltYXRlWzRdLCBzZDEgPSBzZHMueCRzdGRldls1XSxzZDIgPSBzZHMueCRzdGRldls4XSkKCnByaW50KGxpc3QodDFfZXZwLHQxX2V2cyx0Ml9ldnMsdDJfcHZzKSkKCmBgYApTb21lIG9mIHRoZXNlIGFyZSB0b28gbGFyZ2UgdG8gYmUgdHJ1c3RlZC4gVGhpcyBpcyBoYXBwZW5pbmcgYmVjYXVzZSBzb21lIGluZGl2aWR1YWxzIGFyZSBoaWdobHkgc2ltaWxhciBpbiB0aGUgZGF0YS4gV2Ugd2lsbCBoYXZlIHRvIGFja25vd2xlZGdlIHRoaXMgYXMgaXQgaXMgbGlrZWx5IGR1ZSB0byBzbWFsbCBzYW1wbGUgc2l6ZQoKCk1hcmdpbmFsIG1lYW5zIC1ZIFJRMjogTGV0J3MgcmVwZWF0ZSB3aGF0IHdlIGRpZCBmb3IgWCBoZXJlCmBgYHtyfQplbW1feTEgPSBlbW1lYW5zKG1vZF95XzIsIHNwZWNzID0gcGFpcndpc2UgfiBUaW1lUGhhc2V8Um9sZSwgd2VpZ2h0cyA9ICJwcm9wb3J0aW9uYWwiKQplbW1feTEgPSBhc190aWJibGUoZW1tX3kxJGNvbnRyYXN0cykKCmVtbV95MiA9IGVtbWVhbnMobW9kX3lfMiwgc3BlY3MgPSBwYWlyd2lzZSB+IFJvbGV8VGltZVBoYXNlLCB3ZWlnaHRzID0gInByb3BvcnRpb25hbCIpCmVtbV95MiA9IGFzX3RpYmJsZShlbW1feTIkY29udHJhc3RzKQoKZW1tX3kxID0gZW1tX3kxICU+JSBmaWx0ZXIocC52YWx1ZSA8IDAuMDUpCmVtbV95MiA9IGVtbV95MiAlPiUgZmlsdGVyKHAudmFsdWUgPCAwLjA1KQoKZW1tX3kxCmVtbV95MgpgYGAKU2V2ZXJhbCBjb250cmFzdHMgYXJlIHNpZ25pZmljYW50LiBMZXQncyBjYWxjdWxhdGUgdGhlIGVmZmVjdCBzaXplcwoKYGBge3J9CnNkcy55ID0gcmVnX2RhdCAlPiUgZ3JvdXBfYnkoUm9sZSwgYXMuZmFjdG9yKFRpbWVQaGFzZSkpICU+JSBzdW1tYXJpc2Uoc3RkZXYgPSBzZChTVkQyKSkKCiN0aW1lcGhhc2VzIHcvbiBncm91cHMKZW5nX3QxdDNfeSA9IGNvaGVuc2RfMihlbW1feTEkZXN0aW1hdGVbMV0sc2QxID0gc2RzLnkkc3RkZXZbMV0sIHNkMiA9IHNkcy55JHN0ZGV2WzNdKQplbmdfdDJ0M195ID0gY29oZW5zZF8yKGVtbV95MSRlc3RpbWF0ZVsyXSxzZDEgPSBzZHMueSRzdGRldlsyXSwgc2QyID0gc2RzLnkkc3RkZXZbM10pCnBkX3QxdDNfeSA9IGNvaGVuc2RfMihlbW1feTEkZXN0aW1hdGVbM10sc2QxID0gc2RzLnkkc3RkZXZbNF0sIHNkMiA9IHNkcy55JHN0ZGV2WzZdKQpwZF90MnQzX3kgPSBjb2hlbnNkXzIoZW1tX3kxJGVzdGltYXRlWzRdLHNkMSA9IHNkcy55JHN0ZGV2WzVdLCBzZDIgPSBzZHMueSRzdGRldls2XSkKc2RfdDF0Ml95ID0gY29oZW5zZF8yKGVtbV95MSRlc3RpbWF0ZVs1XSxzZDEgPSBzZHMueSRzdGRldls3XSwgc2QyID0gc2RzLnkkc3RkZXZbOF0pCnNkX3QxdDNfeSA9IGNvaGVuc2RfMihlbW1feTEkZXN0aW1hdGVbNl0sc2QxID0gc2RzLnkkc3RkZXZbN10sIHNkMiA9IHNkcy55JHN0ZGV2WzldKQoKcHJpbnQobGlzdChlbmdfdDF0M195LGVuZ190MnQzX3kscGRfdDF0M195LHBkX3QydDNfeSxzZF90MXQyX3ksc2RfdDF0M195KSkgCgoKI2dyb3VwcyB3L24gdGltZXBoYXNlCnQxX2VwX3kgPSBjb2hlbnNkXzIoZW1tX3kyJGVzdGltYXRlWzFdLHNkMSA9IHNkcy55JHN0ZGV2WzFdLCBzZDIgPSBzZHMueSRzdGRldls0XSkKdDFfZXNfeSA9IGNvaGVuc2RfMihlbW1feTIkZXN0aW1hdGVbMl0sc2QxID0gc2RzLnkkc3RkZXZbMV0sIHNkMiA9IHNkcy55JHN0ZGV2WzddKQp0Ml9lcF95ID0gY29oZW5zZF8yKGVtbV95MiRlc3RpbWF0ZVszXSxzZDEgPSBzZHMueSRzdGRldlsyXSwgc2QyID0gc2RzLnkkc3RkZXZbNV0pCnQyX3BzX3kgPSBjb2hlbnNkXzIoZW1tX3kyJGVzdGltYXRlWzRdLHNkMSA9IHNkcy55JHN0ZGV2WzVdLCBzZDIgPSBzZHMueSRzdGRldls4XSkKdDNfZXNfeSA9IGNvaGVuc2RfMihlbW1feTIkZXN0aW1hdGVbNV0sc2QxID0gc2RzLnkkc3RkZXZbM10sIHNkMiA9IHNkcy55JHN0ZGV2WzldKQp0M19wc195ID0gY29oZW5zZF8yKGVtbV95MiRlc3RpbWF0ZVs2XSxzZDEgPSBzZHMueSRzdGRldls2XSwgc2QyID0gc2RzLnkkc3RkZXZbOV0pCgpwcmludChsaXN0KHQxX2VwX3ksdDFfZXNfeSx0Ml9lcF95LHQyX3BzX3ksdDNfZXNfeSx0M19wc195KSkKYGBgCk1vZGVsIGRpYWdub3N0aWNzCmBgYHtyfQpsaWJyYXJ5KHBlcmZvcm1hbmNlKQpsaWJyYXJ5KHNlZSkKCmNoZWNrX21vZGVsKG1vZF94XzIpCmNoZWNrX21vZGVsKG1vZF95XzIpCmBgYApUaGluZ3MgbG9vayBvayBmb3IgdGhlIG1vc3QgcGFydAoKUGxvdCBuZXR3b3JrIHN1YnRyYWN0aW9ucyAocmVwbGFjZSBUaW1lUGhhc2UgYW5kIFJvbGUgZm9yIGRpZmZlcmVudCBjb21iaW5hdGlvbnMpCmBgYHtyfQptZWFuMSA9IHNldF8xJHBvaW50cyAlPiUgZHBseXI6OmZpbHRlcihUaW1lUGhhc2UgPT0gMSwgUm9sZSA9PSAiRW5naW5lZXIiKSAjdXBkYXRlIGhlcmUKbWVhbjIgPSBzZXRfMSRwb2ludHMgJT4lIGRwbHlyOjpmaWx0ZXIoVGltZVBoYXNlID09IDEsIFJvbGUgPT0gIlNlcnZpY2VEZXNpZ25lciIpICN1cGRhdGUgaGVyZQoKbWVhbjFfbmV0ID0gc2V0XzEkbGluZS53ZWlnaHRzICU+JSBkcGx5cjo6ZmlsdGVyKFRpbWVQaGFzZSA9PSAxLCBSb2xlID09ICJFbmdpbmVlciIpICU+JSBjb2xNZWFucygpCm1lYW4yX25ldCA9IHNldF8xJGxpbmUud2VpZ2h0cyAlPiUgZHBseXI6OmZpbHRlcihUaW1lUGhhc2UgPT0gMSwgUm9sZSA9PSAiU2VydmljZURlc2lnbmVyIikgJT4lIGNvbE1lYW5zKCkgI3VwZGF0ZSBoZXJlCgpwbG90KHNldF8xLCB0aXRsZSA9ICJOZXR3b3JrIHN1YnRyYWN0aW9uIikgfD4KICB1bml0cygKICAgIHBvaW50cyA9IG1lYW4xLCAKICAgIHBvaW50c19jb2xvciA9ICJyZWQiLAogICAgc2hvd19tZWFuID0gVFJVRSwgc2hvd19wb2ludHMgPSBGQUxTRSwgd2l0aF9jaSA9IFRSVUUpIHw+CiAgdW5pdHMoCiAgICBwb2ludHMgPSBtZWFuMiwgCiAgICBwb2ludHNfY29sb3IgPSAiYmx1ZSIsCiAgICBzaG93X21lYW4gPSBUUlVFLCBzaG93X3BvaW50cyA9IEZBTFNFLCB3aXRoX2NpID0gVFJVRSkgfD4KICBlZGdlcygKICAgIHdlaWdodHMgPSBtZWFuMV9uZXQgLSBtZWFuMl9uZXQsICMgb3B0aW9uYWwgbXVsdGlwbGllciB0byBhZGp1c3QgZm9yIHJlYWRhYmlsaXR5CiAgICBlZGdlX3NpemVfbXVsdGlwbGllciA9IGVkZ2Vfc2l6ZV9tdWx0aXBsaWVyLAogICAgZWRnZV9hcnJvd19zYXR1cmF0aW9uX211bHRpcGxpZXIgPSBlZGdlX2Fycm93X3NhdHVyYXRpb25fbXVsdGlwbGllciwKICAgIG5vZGVfcG9zaXRpb25fbXVsdGlwbGllciA9IG5vZGVfcG9zaXRpb25fbXVsdGlwbGllciwKICAgIGVkZ2VfY29sb3IgPSBjKCJyZWQiLCJibHVlIikpIHw+CiAgbm9kZXMoCiAgICBub2RlX3NpemVfbXVsdGlwbGllciA9IG5vZGVfc2l6ZV9tdWx0aXBsaWVyLAogICAgbm9kZV9wb3NpdGlvbl9tdWx0aXBsaWVyID0gbm9kZV9wb3NpdGlvbl9tdWx0aXBsaWVyLAogICAgc2VsZl9jb25uZWN0aW9uX2NvbG9yID0gYygicmVkIiwiYmx1ZSIpKQoKCmBgYAoKTW9kZWwgMjogRXBpc3RlbWljIEFnZW5jeSBDb2RlcwoKUGxvdCAxOiBNZWFuIE5ldHdvcmsKCmBgYHtyfQpub2RlX3NpemVfbXVsdGlwbGllciA9IDAuMyAjIHNjYWxlIHVwIG9yIGRvd24gbm9kZSBzaXplcwpub2RlX3Bvc2l0aW9uX211bHRpcGxpZXIgPSAxICMgem9vbSBpbiBvciBvdXQgbm9kZSBwb3NpdGlvbnMKcG9pbnRfcG9zaXRpb25fbXVsdGlwbGllciA9IDEgIyB6b29tIGluIG9yIG91dCB0aGUgcG9pbnQgcG9zaXRpb25zCmVkZ2VfYXJyb3dfc2F0dXJhdGlvbl9tdWx0aXBsaWVyID0gMS41ICMgYWRqdXN0IHRoZSBjaGV2cm9uIGNvbG9yIGxpZ2h0ZXIgb3IgZGFya2VyCmVkZ2Vfc2l6ZV9tdWx0aXBsaWVyID0gMiAjIHNjYWxlIHVwIG9yIGRvd24gZWRnZSBzaXplcwpgYGAKCgpgYGB7cn0KcGxvdChzZXRfMiwgdGl0bGUgPSAiT3ZlcmFsbCBNZWFuLS1BZ2VuY3kiKSB8PgogIHVuaXRzKAogICAgcG9pbnRzPSBzZXRfMiRwb2ludHMsIAogICAgcG9pbnRfcG9zaXRpb25fbXVsdGlwbGllciA9IHBvaW50X3Bvc2l0aW9uX211bHRpcGxpZXIsCiAgICBwb2ludHNfY29sb3IgPSBjKCJibGFjayIpLAogICAgc2hvd19tZWFuID0gVFJVRSwgc2hvd19wb2ludHMgPSBUUlVFLCB3aXRoX2NpID0gVFJVRSkgfD4KICBlZGdlcygKICAgIHdlaWdodHMgPXNldF8yJGxpbmUud2VpZ2h0cywKICAgIGVkZ2Vfc2l6ZV9tdWx0aXBsaWVyID0gZWRnZV9zaXplX211bHRpcGxpZXIsCiAgICBlZGdlX2Fycm93X3NhdHVyYXRpb25fbXVsdGlwbGllciA9IGVkZ2VfYXJyb3dfc2F0dXJhdGlvbl9tdWx0aXBsaWVyLAogICAgbm9kZV9wb3NpdGlvbl9tdWx0aXBsaWVyID0gbm9kZV9wb3NpdGlvbl9tdWx0aXBsaWVyLAogICAgZWRnZV9jb2xvciA9IGMoImJsYWNrIikpIHw+CiAgbm9kZXMoCiAgICBub2RlX3NpemVfbXVsdGlwbGllciA9IG5vZGVfc2l6ZV9tdWx0aXBsaWVyLAogICAgbm9kZV9wb3NpdGlvbl9tdWx0aXBsaWVyID0gbm9kZV9wb3NpdGlvbl9tdWx0aXBsaWVyLAogICAgbm9kZV9sYWJlbHMgPSBUUlVFLCAjIGNoYW5nZSB0aGlzIHRvIEZBTFNFIGNhbiByZW1vdmUgbm9kZSBsYWJlbHMgaW4gY2FzZSB5b3Ugd2FudCB0byBhZGQgdGhlbSBiYWNrIGluIGEgbmljZXIgZm9udCBvciBzaXplIGZvciB5b3VyIHByZXNlbnRhdGlvbnMgb3IgcHVibGljYXRpb25zCiAgICBzZWxmX2Nvbm5lY3Rpb25fY29sb3IgPSBjKCJibGFjayIpKQpgYGAKClBsb3QgMWI6IE92ZXJhbGwgR3JvdXAgQ29tcGFyaXNvbnMKYGBge3J9CnBsb3Qoc2V0XzIsIHRpdGxlID0gIkdyb3VwcyIpIHw+CiAgdW5pdHMoCiAgICBwb2ludHM9IHNldF8yJHBvaW50cyRSb2xlJFByb2R1Y3REZXNpZ25lciwgCiAgICBwb2ludF9wb3NpdGlvbl9tdWx0aXBsaWVyID0gcG9pbnRfcG9zaXRpb25fbXVsdGlwbGllciwKICAgIHBvaW50c19jb2xvciA9IGMoInJlZCIpLAogICAgc2hvd19tZWFuID0gVFJVRSwgc2hvd19wb2ludHMgPSBGQUxTRSwgd2l0aF9jaSA9IFRSVUUpIHw+CiAgIHVuaXRzKAogICAgcG9pbnRzPSBzZXRfMiRwb2ludHMkUm9sZSRFbmdpbmVlciwgCiAgICBwb2ludF9wb3NpdGlvbl9tdWx0aXBsaWVyID0gcG9pbnRfcG9zaXRpb25fbXVsdGlwbGllciwKICAgIHBvaW50c19jb2xvciA9IGMoImJsdWUiKSwKICAgIHNob3dfbWVhbiA9IFRSVUUsIHNob3dfcG9pbnRzID0gRkFMU0UsIHdpdGhfY2kgPSBUUlVFKSB8PgogICB1bml0cygKICAgIHBvaW50cz0gc2V0XzIkcG9pbnRzJFJvbGUkU2VydmljZURlc2lnbmVyLCAKICAgIHBvaW50X3Bvc2l0aW9uX211bHRpcGxpZXIgPSBwb2ludF9wb3NpdGlvbl9tdWx0aXBsaWVyLAogICAgcG9pbnRzX2NvbG9yID0gYygiZ3JlZW4iKSwKICAgIHNob3dfbWVhbiA9IFRSVUUsIHNob3dfcG9pbnRzID0gRkFMU0UsIHdpdGhfY2kgPSBUUlVFKSB8PgogIG5vZGVzKG5vZGVfc2l6ZV9tdWx0aXBsaWVyID0gMC4zLAogICAgICAgICAgICBub2RlX3Bvc2l0aW9uX211bHRpcGxpZXIgPSBub2RlX3Bvc2l0aW9uX211bHRpcGxpZXIsCiAgICAgICAgICAgIHNlbGZfY29ubmVjdGlvbl9jb2xvciA9IGMoImJsYWNrIikpfD4KICAgICAgcGxvdGx5OjpsYXlvdXQoc2hvd2xlZ2VuZCA9IFRSVUUsIGxlZ2VuZCA9IGxpc3QoeCA9IDEwMCwgeSA9IDAuOSkpIHw+CiAgICAgIHBsb3RseTo6c3R5bGUobmFtZSA9ICJQcm9kdWN0IERlc2lnbmVyIiwgdHJhY2VzID0gdHJhY2VzWzFdKSB8PgogICAgICBwbG90bHk6OnN0eWxlKG5hbWUgPSAiRW5naW5lZXIiLCB0cmFjZXMgPSB0cmFjZXNbMl0pIHw+CiAgICAgIHBsb3RseTo6c3R5bGUobmFtZSA9ICJTZXJ2aWNlIERlc2lnbmVyIiwgdHJhY2VzID0gdHJhY2VzWzNdKQogIApgYGAKUGxvdCAxYzogR3JvdXAgc3VidHJhY3Rpb25zCmBgYHtyfQpwcm9kX3B0cyA9IHNldF8yJHBvaW50cyRSb2xlJFByb2R1Y3REZXNpZ25lciAKZW5nX3B0cyA9IHNldF8yJHBvaW50cyRSb2xlJEVuZ2luZWVyCnNlcnZfcHRzID0gc2V0XzIkcG9pbnRzJFJvbGUkU2VydmljZURlc2lnbmVyCgpwcm9kX21lYW5fbmV0ID0gc2V0XzIkbGluZS53ZWlnaHRzICU+JSBkcGx5cjo6ZmlsdGVyKFJvbGUgPT0gIlByb2R1Y3REZXNpZ25lciIpICU+JSBjb2xNZWFucygpCmVuZ19tZWFuX25ldCA9IHNldF8yJGxpbmUud2VpZ2h0cyAlPiUgZHBseXI6OmZpbHRlcihSb2xlID09ICJFbmdpbmVlciIpICU+JSBjb2xNZWFucygpCnNlcnZfbWVhbl9uZXQgPSBzZXRfMiRsaW5lLndlaWdodHMgJT4lIGRwbHlyOjpmaWx0ZXIoUm9sZSA9PSAiU2VydmljZURlc2lnbmVyIikgJT4lIGNvbE1lYW5zKCkKCnBsb3Qoc2V0XzIsIHRpdGxlID0gIlByb2R1Y3QgRGVzaWduZXIgdnMgRW5naW5lZXIiKSB8PgogIHVuaXRzKAogICAgcG9pbnRzID0gcHJvZF9wdHMsIAogICAgcG9pbnRzX2NvbG9yID0gInJlZCIsCiAgICBzaG93X21lYW4gPSBUUlVFLCBzaG93X3BvaW50cyA9IEZBTFNFLCB3aXRoX2NpID0gVFJVRSkgfD4KICB1bml0cygKICAgIHBvaW50cyA9IGVuZ19wdHMsIAogICAgcG9pbnRzX2NvbG9yID0gImJsdWUiLAogICAgc2hvd19tZWFuID0gVFJVRSwgc2hvd19wb2ludHMgPSBGQUxTRSwgd2l0aF9jaSA9IFRSVUUpIHw+CiAgZWRnZXMoCiAgICB3ZWlnaHRzID0gcHJvZF9tZWFuX25ldCAtIGVuZ19tZWFuX25ldCwgIyBvcHRpb25hbCBtdWx0aXBsaWVyIHRvIGFkanVzdCBmb3IgcmVhZGFiaWxpdHkKICAgIGVkZ2Vfc2l6ZV9tdWx0aXBsaWVyID0gZWRnZV9zaXplX211bHRpcGxpZXIsCiAgICBlZGdlX2Fycm93X3NhdHVyYXRpb25fbXVsdGlwbGllciA9IGVkZ2VfYXJyb3dfc2F0dXJhdGlvbl9tdWx0aXBsaWVyLAogICAgbm9kZV9wb3NpdGlvbl9tdWx0aXBsaWVyID0gbm9kZV9wb3NpdGlvbl9tdWx0aXBsaWVyLAogICAgZWRnZV9jb2xvciA9IGMoInJlZCIsImJsdWUiKSkgfD4KICBub2RlcygKICAgIG5vZGVfc2l6ZV9tdWx0aXBsaWVyID0gbm9kZV9zaXplX211bHRpcGxpZXIsCiAgICBub2RlX3Bvc2l0aW9uX211bHRpcGxpZXIgPSBub2RlX3Bvc2l0aW9uX211bHRpcGxpZXIsCiAgICBzZWxmX2Nvbm5lY3Rpb25fY29sb3IgPSBjKCJyZWQiLCJibHVlIikpCgpwbG90KHNldF8yLCB0aXRsZSA9ICJQcm9kdWN0IERlc2lnbmVyIHZzIFNlcnZpY2VEZXNpZ25lciIpIHw+CiAgdW5pdHMoCiAgICBwb2ludHMgPSBwcm9kX3B0cywgCiAgICBwb2ludHNfY29sb3IgPSAicmVkIiwKICAgIHNob3dfbWVhbiA9IFRSVUUsIHNob3dfcG9pbnRzID0gRkFMU0UsIHdpdGhfY2kgPSBUUlVFKSB8PgogIHVuaXRzKAogICAgcG9pbnRzID1zZXJ2X3B0cywgCiAgICBwb2ludHNfY29sb3IgPSAiZ3JlZW4iLAogICAgc2hvd19tZWFuID0gVFJVRSwgc2hvd19wb2ludHMgPSBGQUxTRSwgd2l0aF9jaSA9IFRSVUUpIHw+CiAgZWRnZXMoCiAgICB3ZWlnaHRzID0gcHJvZF9tZWFuX25ldCAtIHNlcnZfbWVhbl9uZXQsICMgb3B0aW9uYWwgbXVsdGlwbGllciB0byBhZGp1c3QgZm9yIHJlYWRhYmlsaXR5CiAgICBlZGdlX3NpemVfbXVsdGlwbGllciA9IGVkZ2Vfc2l6ZV9tdWx0aXBsaWVyLAogICAgZWRnZV9hcnJvd19zYXR1cmF0aW9uX211bHRpcGxpZXIgPSBlZGdlX2Fycm93X3NhdHVyYXRpb25fbXVsdGlwbGllciwKICAgIG5vZGVfcG9zaXRpb25fbXVsdGlwbGllciA9IG5vZGVfcG9zaXRpb25fbXVsdGlwbGllciwKICAgIGVkZ2VfY29sb3IgPSBjKCJyZWQiLCJncmVlbiIpKSB8PgogIG5vZGVzKAogICAgbm9kZV9zaXplX211bHRpcGxpZXIgPSBub2RlX3NpemVfbXVsdGlwbGllciwKICAgIG5vZGVfcG9zaXRpb25fbXVsdGlwbGllciA9IG5vZGVfcG9zaXRpb25fbXVsdGlwbGllciwKICAgIHNlbGZfY29ubmVjdGlvbl9jb2xvciA9IGMoInJlZCIsImdyZWVuIikpCgpwbG90KHNldF8yLCB0aXRsZSA9ICJTZXJ2aWNlIERlc2lnbmVyIHZzIEVuZ2luZWVyIikgfD4KICB1bml0cygKICAgIHBvaW50cyA9IHNlcnZfcHRzLCAKICAgIHBvaW50c19jb2xvciA9ICJncmVlbiIsCiAgICBzaG93X21lYW4gPSBUUlVFLCBzaG93X3BvaW50cyA9IEZBTFNFLCB3aXRoX2NpID0gVFJVRSkgfD4KICB1bml0cygKICAgIHBvaW50cyA9IGVuZ19wdHMsIAogICAgcG9pbnRzX2NvbG9yID0gImJsdWUiLAogICAgc2hvd19tZWFuID0gVFJVRSwgc2hvd19wb2ludHMgPSBGQUxTRSwgd2l0aF9jaSA9IFRSVUUpIHw+CiAgZWRnZXMoCiAgICB3ZWlnaHRzID0gc2Vydl9tZWFuX25ldCAtIGVuZ19tZWFuX25ldCwgIyBvcHRpb25hbCBtdWx0aXBsaWVyIHRvIGFkanVzdCBmb3IgcmVhZGFiaWxpdHkKICAgIGVkZ2Vfc2l6ZV9tdWx0aXBsaWVyID0gMSwKICAgIGVkZ2VfYXJyb3dfc2F0dXJhdGlvbl9tdWx0aXBsaWVyID0gZWRnZV9hcnJvd19zYXR1cmF0aW9uX211bHRpcGxpZXIsCiAgICBub2RlX3Bvc2l0aW9uX211bHRpcGxpZXIgPSBub2RlX3Bvc2l0aW9uX211bHRpcGxpZXIsCiAgICBlZGdlX2NvbG9yID0gYygiZ3JlZW4iLCJibHVlIikpIHw+CiAgbm9kZXMoCiAgICBub2RlX3NpemVfbXVsdGlwbGllciA9IG5vZGVfc2l6ZV9tdWx0aXBsaWVyLAogICAgbm9kZV9wb3NpdGlvbl9tdWx0aXBsaWVyID0gbm9kZV9wb3NpdGlvbl9tdWx0aXBsaWVyLAogICAgc2VsZl9jb25uZWN0aW9uX2NvbG9yID0gYygiZ3JlZW4iLCJibHVlIikpCmBgYAoKUGxvdCAyOiBBbGwgTWVhbnMKYGBge3J9CgojZ2V0IGxpc3Qgb2YgdGltZSBwaGFzZXMgYW5kIGdyb3VwcyBsb29wIG92ZXIgb3IgdXNlIG1hcCBmdW5jdGlvbgoKcGhhc2VzID0gdW5pcXVlKHNldF8yJHBvaW50cyRUaW1lUGhhc2UpCgpncm91cHMgPSB1bmlxdWUoc2V0XzIkcG9pbnRzJFJvbGUpCgoKY29sX2xpc3RfMiA9IGMoInJlZCIsCiAgICAgICAgICAgICAgImJsdWUiLAogICAgICAgICAgICAgICJncmVlbiIpCgp0cmFjZXMgPSBjKDI6MTApCgp4X2FnZW5jeSA9IHBsb3Qoc2V0XzIsIHRpdGxlID0gIkdyb3VwIE1lYW5zIGJ5IFBoYXNlIC0tIEFnZW5jeSIpCmNvdW50ID0gMQoKZm9yIChpIGluIDE6bGVuZ3RoKHBoYXNlcykpewogIGZvciAoaiBpbiAxOmxlbmd0aChncm91cHMpKXsKICAgIHBvaW50cyA9IHNldF8yJHBvaW50cyAlPiUgZmlsdGVyKFRpbWVQaGFzZSA9PSBwaGFzZXNbaV0sIFJvbGUgPT0gZ3JvdXBzW2pdKQogICAgI3ByaW50KGhlYWQocG9pbnRzKSkKICAgIHhfYWdlbmN5ID0geF9hZ2VuY3kgfD4KICAgICAgdW5pdHMoCiAgICAgICAgcG9pbnRzID0gcG9pbnRzLAogICAgICAgIHBvaW50X3Bvc2l0aW9uX211bHRpcGxpZXIgPSBwb2ludF9wb3NpdGlvbl9tdWx0aXBsaWVyLAogICAgICAgIHBvaW50c19jb2xvciA9IGNvbF9saXN0XzJbaV0sCiAgICAgICAgc2hvd19tZWFuID0gVFJVRSwgc2hvd19wb2ludHMgPSBGLCB3aXRoX2NpID0gRkFMU0UKICAgICAgICApIHw+CiAgICAgIG5vZGVzKG5vZGVfc2l6ZV9tdWx0aXBsaWVyID0gMC4zLAogICAgICAgICAgICBub2RlX3Bvc2l0aW9uX211bHRpcGxpZXIgPSBub2RlX3Bvc2l0aW9uX211bHRpcGxpZXIsCiAgICAgICAgICAgIHNlbGZfY29ubmVjdGlvbl9jb2xvciA9IGMoImJsYWNrIikpfD4KICAgICAgcGxvdGx5OjpsYXlvdXQoc2hvd2xlZ2VuZCA9IFRSVUUsIGxlZ2VuZCA9IGxpc3QoeCA9IDEwMCwgeSA9IDAuOSkpIHw+CiAgICAgIHBsb3RseTo6c3R5bGUobmFtZSA9IHBhc3RlMChwaGFzZXNbaV0sIiAtICIsZ3JvdXBzW2pdKSwgdHJhY2VzID0gdHJhY2VzW2NvdW50XSkKICAgIGNvdW50ID0gY291bnQgKyAxCiAgICAKICB9Cn0KCnhfYWdlbmN5CmBgYAoKQ2hlY2sgbmVzdGluZwoKYGBge3J9CnJlZ19kYXRfYWdlbmN5ID0gc2V0XzIkcG9pbnRzICU+JSBmaWx0ZXIoRU5BX0RJUkVDVElPTiA9PSAicmVzcG9uc2UiKQoKSUNDOjpJQ0Nlc3QoU3BlYWtlcixTVkQxLHJlZ19kYXRfYWdlbmN5KSAjbm90IHNpZ25pZmljYW50CgpJQ0M6OklDQ2VzdChTcGVha2VyLFNWRDIscmVnX2RhdF9hZ2VuY3kpICNzaWduaWZpY2FudCB3ZSB3aWxsIG5lZWQgdG8gaW5jbHVkZSBhIHZhcmlhYmxlIGZvciBpbmRpdmlkdWFsIGluIHRoZSBtb2RlbApgYGAKCgpgYGB7cn0KbW9kX3hfYWdlbmN5ID0gbG0oU1ZEMSB+IGFzLmZhY3RvcihUaW1lUGhhc2UpICsgUm9sZSwgZGF0YSA9IHJlZ19kYXRfYWdlbmN5KQptb2RfeV9hZ2VuY3kgPSBsbShTVkQyIH4gYXMuZmFjdG9yKFRpbWVQaGFzZSkgKyBSb2xlLCBkYXRhID0gcmVnX2RhdF9hZ2VuY3kpCgoKc3VtbWFyeShtb2RfeF9hZ2VuY3kpCnN1bW1hcnkobW9kX3lfYWdlbmN5KQpgYGAKCmNoZWNrIGZvciBpbnRlcmFjdGlvbnM6IChpbnRlcmFjdGlvbnMgYXJlIHNpZ25pZmljYW50IHNvIHdlIHNob3VsZCB1c2UgdGhvc2UgbW9kZXMpCmBgYHtyfQptb2RfeF9hZ2VuY3lfMiA9IGxtKFNWRDEgfiBhcy5mYWN0b3IoVGltZVBoYXNlKSArIFJvbGUgKyBhcy5mYWN0b3IoVGltZVBoYXNlKSpSb2xlLCBkYXRhID0gcmVnX2RhdF9hZ2VuY3kpCm1vZF95X2FnZW5jeV8yID0gbG0oU1ZEMiB+IGFzLmZhY3RvcihUaW1lUGhhc2UpICsgUm9sZSArIGFzLmZhY3RvcihUaW1lUGhhc2UpKlJvbGUsIGRhdGEgPSByZWdfZGF0X2FnZW5jeSkKCnN1bW1hcnkobW9kX3hfYWdlbmN5XzIpCnN1bW1hcnkobW9kX3lfYWdlbmN5XzIpCgphbm92YShtb2RfeF9hZ2VuY3ksbW9kX3hfYWdlbmN5XzIpCmFub3ZhKG1vZF95X2FnZW5jeSxtb2RfeV9hZ2VuY3lfMikKCmBgYAoKI05lZWQgdG8gcnVuIG1peGVkIG1vZGVsIGZvciBZCiMjbW9kZWwgaXMgc2luZ3VsYXIgc28gc3RpY2sgd2l0aCBPTFMKCmBgYHtyfQpsaWJyYXJ5KGxtZXJUZXN0KQoKbW9kX3lfYWdlbmN5X21peGVkID0gbG1lclRlc3Q6OmxtZXIoU1ZEMiB+IDEgKyAoMXxTcGVha2VyKSArIGFzLmZhY3RvcihUaW1lUGhhc2UpKlJvbGUgLGRhdGEgPSByZWdfZGF0X2FnZW5jeSkKCnN1bW1hcnkobW9kX3lfYWdlbmN5X21peGVkKQpgYGAKCgoKTWFyZ2luYWwgbWVhbnMgeCAtIFJRMQpgYGB7cn0KZW1tX2FnMSA9IGVtbWVhbnMobW9kX3hfYWdlbmN5XzIsIHNwZWNzID0gcGFpcndpc2UgfiBSb2xlLCB3ZWlnaHRzID0gInByb3BvcnRpb25hbCIpCnByaW50KGVtbV9hZzEkZW1tZWFucykKcHJpbnQoZW1tX2FnMSRjb250cmFzdHMpCmBgYAoKVmlld2luZyBpbnRlcmFjdGlvbnMKYGBge3J9CmVtbWlwKG1vZF94X2FnZW5jeV8yLCBSb2xlIH4gVGltZVBoYXNlKQoKYGBgCgoKTWFyZ2luYWwgbWVhbnMgLSB4IFJRMgpgYGB7cn0KZW1tX2FnMSA9IGVtbWVhbnMobW9kX3hfYWdlbmN5XzIsIHNwZWNzID0gcGFpcndpc2UgfiBUaW1lUGhhc2V8Um9sZSwgd2VpZ2h0cyA9ICJwcm9wb3J0aW9uYWwiKQplbW1fYWcxJGNvbnRyYXN0cwoKZW1tX2FnMiA9IGVtbWVhbnMobW9kX3hfYWdlbmN5XzIsIHNwZWNzID0gcGFpcndpc2UgfiBSb2xlfFRpbWVQaGFzZSwgd2VpZ2h0cyA9ICJwcm9wb3J0aW9uYWwiKQplbW1fYWcyJGNvbnRyYXN0cwoKYGBgCk1hcmdpbmFsIG1lYW5zIHkgLSBSUTEKYGBge3J9CmVtbV9hZ195MSA9IGVtbWVhbnMobW9kX3lfYWdlbmN5XzIsIHNwZWNzID0gcGFpcndpc2UgfiBSb2xlLCB3ZWlnaHRzID0gInByb3BvcnRpb25hbCIpCnByaW50KGVtbV9hZ195MSRlbW1lYW5zKQpwcmludChlbW1fYWdfeTEkY29udHJhc3RzKQpgYGAKClZpZXdpbmcgaW50ZXJhY3Rpb25zCmBgYHtyfQplbW1pcChtb2RfeV9hZ2VuY3lfMiwgUm9sZSB+IFRpbWVQaGFzZSkKYGBgCgpNYXJnaW5hbCBtZWFucyAtIHkgUlEyCmBgYHtyfQplbW1fYWdfeTEgPSBlbW1lYW5zKG1vZF95X2FnZW5jeV8yLCBzcGVjcyA9IHBhaXJ3aXNlIH4gVGltZVBoYXNlfFJvbGUsIHdlaWdodHMgPSAicHJvcG9ydGlvbmFsIikKZW1tX2FnX3kxJGNvbnRyYXN0cwoKZW1tX2FnX3kyID0gZW1tZWFucyhtb2RfeV9hZ2VuY3lfMiwgc3BlY3MgPSBwYWlyd2lzZSB+IFJvbGV8VGltZVBoYXNlLCB3ZWlnaHRzID0gInByb3BvcnRpb25hbCIpCmVtbV9hZ195MiRjb250cmFzdHMKYGBgCgpDYWxjdWxhdGUgZWZmIHNpemVzCmBgYHtyfQojdG8gZG8KYGBgCgoKTW9kZWwgZGlhZ25vc3RpY3MKYGBge3J9CmNoZWNrX21vZGVsKG1vZF94X2FnZW5jeV8yKQpjaGVja19tb2RlbChtb2RfeV9hZ2VuY3lfMikKYGBgCgoKUGxvdCBuZXR3b3JrIHN1YnRyYWN0aW9ucwpgYGB7cn0KbWVhbjEgPSBzZXRfMiRwb2ludHMgJT4lIGRwbHlyOjpmaWx0ZXIoVGltZVBoYXNlID09IDEsIFJvbGUgPT0gIkVuZ2luZWVyIikKbWVhbjIgPSBzZXRfMiRwb2ludHMgJT4lIGRwbHlyOjpmaWx0ZXIoVGltZVBoYXNlID09IDEsIFJvbGUgPT0gIlByb2R1Y3REZXNpZ25lciIpCgptZWFuMV9uZXQgPSBzZXRfMiRsaW5lLndlaWdodHMgJT4lIGRwbHlyOjpmaWx0ZXIoVGltZVBoYXNlID09IDEsIFJvbGUgPT0gIkVuZ2luZWVyIikgJT4lIGNvbE1lYW5zKCkKbWVhbjJfbmV0ID0gc2V0XzIkbGluZS53ZWlnaHRzICU+JSBkcGx5cjo6ZmlsdGVyKFRpbWVQaGFzZSA9PSAxLCBSb2xlID09ICJQcm9kdWN0RGVzaWduZXIiKSAlPiUgY29sTWVhbnMoKQoKcGxvdChzZXRfMiwgdGl0bGUgPSAiTmV0d29yayBzdWJ0cmFjdGlvbiIpIHw+CiAgdW5pdHMoCiAgICBwb2ludHMgPSBtZWFuMSwgCiAgICBwb2ludHNfY29sb3IgPSAicmVkIiwKICAgIHNob3dfbWVhbiA9IFRSVUUsIHNob3dfcG9pbnRzID0gRkFMU0UsIHdpdGhfY2kgPSBUUlVFKSB8PgogIHVuaXRzKAogICAgcG9pbnRzID0gbWVhbjIsIAogICAgcG9pbnRzX2NvbG9yID0gImJsdWUiLAogICAgc2hvd19tZWFuID0gVFJVRSwgc2hvd19wb2ludHMgPSBGQUxTRSwgd2l0aF9jaSA9IFRSVUUpIHw+CiAgZWRnZXMoCiAgICB3ZWlnaHRzID0gbWVhbjFfbmV0IC0gbWVhbjJfbmV0LCAjIG9wdGlvbmFsIG11bHRpcGxpZXIgdG8gYWRqdXN0IGZvciByZWFkYWJpbGl0eQogICAgZWRnZV9zaXplX211bHRpcGxpZXIgPSBlZGdlX3NpemVfbXVsdGlwbGllciwKICAgIGVkZ2VfYXJyb3dfc2F0dXJhdGlvbl9tdWx0aXBsaWVyID0gZWRnZV9hcnJvd19zYXR1cmF0aW9uX211bHRpcGxpZXIsCiAgICBub2RlX3Bvc2l0aW9uX211bHRpcGxpZXIgPSBub2RlX3Bvc2l0aW9uX211bHRpcGxpZXIsCiAgICBlZGdlX2NvbG9yID0gYygicmVkIiwiYmx1ZSIpKSB8PgogIG5vZGVzKAogICAgbm9kZV9zaXplX211bHRpcGxpZXIgPSBub2RlX3NpemVfbXVsdGlwbGllciwKICAgIG5vZGVfcG9zaXRpb25fbXVsdGlwbGllciA9IG5vZGVfcG9zaXRpb25fbXVsdGlwbGllciwKICAgIHNlbGZfY29ubmVjdGlvbl9jb2xvciA9IGMoInJlZCIsImJsdWUiKSkKYGBgCgoK